Adding comments
[privoxy.git] / src / loadcfg.c
1 const char loadcfg_rcs[] = "$Id: loadcfg.c,v 2.0 2002/06/04 14:34:21 jongfoster Exp $";
2 /*********************************************************************
3  *
4  * File        :  $Source: /cvsroot/ijbswa/current/src/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  *                Privoxy team. http://www.privoxy.org/
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 2.0  2002/06/04 14:34:21  jongfoster
39  *    Moving source files to src/
40  *
41  *    Revision 1.48  2002/05/14 21:30:38  oes
42  *    savearg now uses own linking code instead of (now special-cased) add_help_link
43  *
44  *    Revision 1.47  2002/05/12 21:36:29  jongfoster
45  *    Correcting function comments
46  *
47  *    Revision 1.46  2002/04/26 12:55:14  oes
48  *     - New option "user-manual", defaults to our site
49  *       via project.h #define
50  *     - savearg now embeds option names in help links
51  *
52  *    Revision 1.45  2002/04/24 02:11:54  oes
53  *    Jon's multiple AF patch: Allow up to MAX_ACTION_FILES actionsfile options
54  *
55  *    Revision 1.44  2002/04/08 20:37:13  swa
56  *    fixed JB spelling
57  *
58  *    Revision 1.43  2002/04/08 20:36:50  swa
59  *    fixed JB spelling
60  *
61  *    Revision 1.42  2002/04/05 15:50:15  oes
62  *    fix for invalid HTML proxy_args
63  *
64  *    Revision 1.41  2002/03/31 17:19:00  jongfoster
65  *    Win32 only: Enabling STRICT to fix a VC++ compile warning.
66  *
67  *    Revision 1.40  2002/03/26 22:29:55  swa
68  *    we have a new homepage!
69  *
70  *    Revision 1.39  2002/03/24 13:25:43  swa
71  *    name change related issues
72  *
73  *    Revision 1.38  2002/03/24 13:05:48  jongfoster
74  *    Renaming re_filterfile to filterfile
75  *
76  *    Revision 1.37  2002/03/16 23:54:06  jongfoster
77  *    Adding graceful termination feature, to help look for memory leaks.
78  *    If you enable this (which, by design, has to be done by hand
79  *    editing config.h) and then go to http://i.j.b/die, then the program
80  *    will exit cleanly after the *next* request.  It should free all the
81  *    memory that was used.
82  *
83  *    Revision 1.36  2002/03/13 00:27:05  jongfoster
84  *    Killing warnings
85  *
86  *    Revision 1.35  2002/03/07 03:52:44  oes
87  *    Set logging to tty for --no-daemon mode
88  *
89  *    Revision 1.34  2002/03/06 23:14:35  jongfoster
90  *    Trivial cosmetic changes to make function comments easier to find.
91  *
92  *    Revision 1.33  2002/03/05 04:52:42  oes
93  *    Deleted non-errlog debugging code
94  *
95  *    Revision 1.32  2002/03/04 18:24:53  oes
96  *    Re-enabled output of unknown config directive hash
97  *
98  *    Revision 1.31  2002/03/03 15:07:20  oes
99  *    Re-enabled automatic config reloading
100  *
101  *    Revision 1.30  2002/01/22 23:31:43  jongfoster
102  *    Replacing strsav() with string_append()
103  *
104  *    Revision 1.29  2002/01/17 21:02:30  jongfoster
105  *    Moving all our URL and URL pattern parsing code to urlmatch.c.
106  *
107  *    Renaming free_url to free_url_spec, since it frees a struct url_spec.
108  *
109  *    Revision 1.28  2001/12/30 14:07:32  steudten
110  *    - Add signal handling (unix)
111  *    - Add SIGHUP handler (unix)
112  *    - Add creation of pidfile (unix)
113  *    - Add action 'top' in rc file (RH)
114  *    - Add entry 'SIGNALS' to manpage
115  *    - Add exit message to logfile (unix)
116  *
117  *    Revision 1.27  2001/11/07 00:02:13  steudten
118  *    Add line number in error output for lineparsing for
119  *    actionsfile and configfile.
120  *    Special handling for CLF added.
121  *
122  *    Revision 1.26  2001/11/05 21:41:43  steudten
123  *    Add changes to be a real daemon just for unix os.
124  *    (change cwd to /, detach from controlling tty, set
125  *    process group and session leader to the own process.
126  *    Add DBG() Macro.
127  *    Add some fatal-error log message for failed malloc().
128  *    Add '-d' if compiled with 'configure --with-debug' to
129  *    enable debug output.
130  *
131  *    Revision 1.25  2001/10/25 03:40:48  david__schmidt
132  *    Change in porting tactics: OS/2's EMX porting layer doesn't allow multiple
133  *    threads to call select() simultaneously.  So, it's time to do a real, live,
134  *    native OS/2 port.  See defines for __EMX__ (the porting layer) vs. __OS2__
135  *    (native). Both versions will work, but using __OS2__ offers multi-threading.
136  *
137  *    Revision 1.24  2001/10/23 21:40:30  jongfoster
138  *    Added support for enable-edit-actions and enable-remote-toggle config
139  *    file options.
140  *
141  *    Revision 1.23  2001/10/07 15:36:00  oes
142  *    Introduced new config option "buffer-limit"
143  *
144  *    Revision 1.22  2001/09/22 16:36:59  jongfoster
145  *    Removing unused parameter fs from read_config_line()
146  *
147  *    Revision 1.21  2001/09/16 17:10:43  jongfoster
148  *    Moving function savearg() here, since it was the only thing left in
149  *    showargs.c.
150  *
151  *    Revision 1.20  2001/07/30 22:08:36  jongfoster
152  *    Tidying up #defines:
153  *    - All feature #defines are now of the form FEATURE_xxx
154  *    - Permanently turned off WIN_GUI_EDIT
155  *    - Permanently turned on WEBDAV and SPLIT_PROXY_ARGS
156  *
157  *    Revision 1.19  2001/07/15 17:45:16  jongfoster
158  *    Removing some unused #includes
159  *
160  *    Revision 1.18  2001/07/13 14:01:14  oes
161  *     - Removed all #ifdef PCRS
162  *     - Removed vim-settings
163  *
164  *    Revision 1.17  2001/06/29 13:31:03  oes
165  *    - Improved comments
166  *    - Fixed (actionsfile) and sorted hashes
167  *    - Introduced admin_address and proxy-info-url
168  *      as config parameters
169  *    - Renamed config->proxy_args_invocation (which didn't have
170  *      the invocation but the options!) to config->proxy_args
171  *    - Various adaptions
172  *    - Removed logentry from cancelled commit
173  *
174  *    Revision 1.16  2001/06/09 10:55:28  jongfoster
175  *    Changing BUFSIZ ==> BUFFER_SIZE
176  *
177  *    Revision 1.15  2001/06/07 23:13:40  jongfoster
178  *    Merging ACL and forward files into config file.
179  *    Cosmetic: Sorting config file options alphabetically.
180  *    Cosmetic: Adding brief syntax comments to config file options.
181  *
182  *    Revision 1.14  2001/06/07 14:46:25  joergs
183  *    Missing make_path() added for re_filterfile.
184  *
185  *    Revision 1.13  2001/06/05 22:33:54  jongfoster
186  *
187  *    Fixed minor memory leak.
188  *    Also now uses make_path to prepend the pathnames.
189  *
190  *    Revision 1.12  2001/06/05 20:04:09  jongfoster
191  *    Now uses _snprintf() in place of snprintf() under Win32.
192  *
193  *    Revision 1.11  2001/06/04 18:31:58  swa
194  *    files are now prefixed with either `confdir' or `logdir'.
195  *    `make redhat-dist' replaces both entries confdir and logdir
196  *    with redhat values
197  *
198  *    Revision 1.10  2001/06/03 19:11:54  oes
199  *    introduced confdir option
200  *
201  *    Revision 1.9  2001/06/01 20:06:24  jongfoster
202  *    Removed support for "tinygif" option - moved to actions file.
203  *
204  *    Revision 1.8  2001/05/31 21:27:13  jongfoster
205  *    Removed many options from the config file and into the
206  *    "actions" file: add_forwarded, suppress_vanilla_wafer,
207  *    wafer, add_header, user_agent, referer, from
208  *    Also globally replaced "permission" with "action".
209  *
210  *    Revision 1.7  2001/05/29 09:50:24  jongfoster
211  *    Unified blocklist/imagelist/permissionslist.
212  *    File format is still under discussion, but the internal changes
213  *    are (mostly) done.
214  *
215  *    Also modified interceptor behaviour:
216  *    - We now intercept all URLs beginning with one of the following
217  *      prefixes (and *only* these prefixes):
218  *        * http://i.j.b/
219  *        * http://ijbswa.sf.net/config/
220  *        * http://ijbswa.sourceforge.net/config/
221  *    - New interceptors "home page" - go to http://i.j.b/ to see it.
222  *    - Internal changes so that intercepted and fast redirect pages
223  *      are not replaced with an image.
224  *    - Interceptors now have the option to send a binary page direct
225  *      to the client. (i.e. ijb-send-banner uses this)
226  *    - Implemented show-url-info interceptor.  (Which is why I needed
227  *      the above interceptors changes - a typical URL is
228  *      "http://i.j.b/show-url-info?url=www.somesite.com/banner.gif".
229  *      The previous mechanism would not have intercepted that, and
230  *      if it had been intercepted then it then it would have replaced
231  *      it with an image.)
232  *
233  *    Revision 1.6  2001/05/26 00:28:36  jongfoster
234  *    Automatic reloading of config file.
235  *    Removed obsolete SIGHUP support (Unix) and Reload menu option (Win32).
236  *    Most of the global variables have been moved to a new
237  *    struct configuration_spec, accessed through csp->config->globalname
238  *    Most of the globals remaining are used by the Win32 GUI.
239  *
240  *    Revision 1.5  2001/05/25 22:34:30  jongfoster
241  *    Hard tabs->Spaces
242  *
243  *    Revision 1.4  2001/05/22 18:46:04  oes
244  *
245  *    - Enabled filtering banners by size rather than URL
246  *      by adding patterns that replace all standard banner
247  *      sizes with the "Junkbuster" gif to the re_filterfile
248  *
249  *    - Enabled filtering WebBugs by providing a pattern
250  *      which kills all 1x1 images
251  *
252  *    - Added support for PCRE_UNGREEDY behaviour to pcrs,
253  *      which is selected by the (nonstandard and therefore
254  *      capital) letter 'U' in the option string.
255  *      It causes the quantifiers to be ungreedy by default.
256  *      Appending a ? turns back to greedy (!).
257  *
258  *    - Added a new interceptor ijb-send-banner, which
259  *      sends back the "Junkbuster" gif. Without imagelist or
260  *      MSIE detection support, or if tinygif = 1, or the
261  *      URL isn't recognized as an imageurl, a lame HTML
262  *      explanation is sent instead.
263  *
264  *    - Added new feature, which permits blocking remote
265  *      script redirects and firing back a local redirect
266  *      to the browser.
267  *      The feature is conditionally compiled, i.e. it
268  *      can be disabled with --disable-fast-redirects,
269  *      plus it must be activated by a "fast-redirects"
270  *      line in the config file, has its own log level
271  *      and of course wants to be displayed by show-proxy-args
272  *      Note: Boy, all the #ifdefs in 1001 locations and
273  *      all the fumbling with configure.in and acconfig.h
274  *      were *way* more work than the feature itself :-(
275  *
276  *    - Because a generic redirect template was needed for
277  *      this, tinygif = 3 now uses the same.
278  *
279  *    - Moved GIFs, and other static HTTP response templates
280  *      to project.h
281  *
282  *    - Some minor fixes
283  *
284  *    - Removed some >400 CRs again (Jon, you really worked
285  *      a lot! ;-)
286  *
287  *    Revision 1.3  2001/05/20 01:21:20  jongfoster
288  *    Version 2.9.4 checkin.
289  *    - Merged popupfile and cookiefile, and added control over PCRS
290  *      filtering, in new "permissionsfile".
291  *    - Implemented LOG_LEVEL_FATAL, so that if there is a configuration
292  *      file error you now get a message box (in the Win32 GUI) rather
293  *      than the program exiting with no explanation.
294  *    - Made killpopup use the PCRS MIME-type checking and HTTP-header
295  *      skipping.
296  *    - Removed tabs from "config"
297  *    - Moved duplicated url parsing code in "loaders.c" to a new funcition.
298  *    - Bumped up version number.
299  *
300  *    Revision 1.2  2001/05/17 23:01:01  oes
301  *     - Cleaned CRLF's from the sources and related files
302  *
303  *    Revision 1.1.1.1  2001/05/15 13:58:58  oes
304  *    Initial import of version 2.9.3 source tree
305  *
306  *
307  *********************************************************************/
308 \f
309
310 #include "config.h"
311
312 #include <stdio.h>
313 #include <sys/types.h>
314 #include <stdlib.h>
315 #include <string.h>
316 #include <signal.h>
317 #include <fcntl.h>
318 #include <errno.h>
319 #include <ctype.h>
320 #include <assert.h>
321
322 #ifdef _WIN32
323
324 # ifndef STRICT
325 #  define STRICT
326 # endif
327 # include <windows.h>
328
329 # include "win32.h"
330 # ifndef _WIN_CONSOLE
331 #  include "w32log.h"
332 # endif /* ndef _WIN_CONSOLE */
333
334 /* VC++ has "_snprintf", not "snprintf" */
335 #define snprintf _snprintf
336
337 #else /* ifndef _WIN32 */
338
339 #ifndef __OS2__
340 # include <unistd.h>
341 # include <sys/wait.h>
342 #endif
343 # include <sys/time.h>
344 # include <sys/stat.h>
345 # include <signal.h>
346
347 #endif
348
349 #include "loadcfg.h"
350 #include "list.h"
351 #include "jcc.h"
352 #include "filters.h"
353 #include "loaders.h"
354 #include "miscutil.h"
355 #include "errlog.h"
356 #include "ssplit.h"
357 #include "encode.h"
358 #include "urlmatch.h"
359 #include "cgi.h"
360
361 const char loadcfg_h_rcs[] = LOADCFG_H_VERSION;
362
363 /*
364  * Fix a problem with Solaris.  There should be no effect on other
365  * platforms.
366  * Solaris's isspace() is a macro which uses it's argument directly
367  * as an array index.  Therefore we need to make sure that high-bit
368  * characters generate +ve values, and ideally we also want to make
369  * the argument match the declared parameter type of "int".
370  */
371 #define ijb_isupper(__X) isupper((int)(unsigned char)(__X))
372 #define ijb_tolower(__X) tolower((int)(unsigned char)(__X))
373
374 #ifdef FEATURE_TOGGLE
375 /**
376  * Indicates if Privoxy is currently enabled.
377  */
378 int g_bToggleIJB        = 1;   /* Privoxy is enabled by default. */
379 #endif /* def FEATURE_TOGGLE */
380
381 /**
382  * The filename of the config file
383  */
384 const char *configfile  = NULL;
385
386 /**
387  * Global argument count, so that CGI functions can access the
388  * command line.
389  */
390 int Argc = 0;
391
392 /**
393  * Global argument list, so that CGI functions can access the
394  * command line.
395  */
396 const char **Argv = NULL;
397
398 /**
399  * The configuration file which is currently loaded.
400  */
401 static struct file_list *current_configfile = NULL;
402
403
404 /*
405  * This takes the "cryptic" hash of each keyword and aliases them to
406  * something a little more readable.  This also makes changing the
407  * hash values easier if they should change or the hash algorthm changes.
408  * Use the included "hash" program to find out what the hash will be
409  * for any string supplied on the command line.  (Or just put it in the
410  * config file and read the number from the error message in the log).
411  *
412  * Please keep this list sorted alphabetically (but with the Windows
413  * console and GUI specific options last).
414  */
415
416 #define hash_actions_file              1196306641ul /**< "actionsfile" */
417 #define hash_admin_address             4112573064ul /**< "admin-address" */
418 #define hash_buffer_limit              1881726070ul /**< "buffer-limit */
419 #define hash_confdir                      1978389ul /**< "confdir" */
420 #define hash_debug                          78263ul /**< "debug" */
421 #define hash_deny_access               1227333715ul /**< "deny-access" */
422 #define hash_enable_edit_actions       2517097536ul /**< "enable-edit-actions" */
423 #define hash_enable_remote_toggle      2979744683ul /**< "enable-remote-toggle" */
424 #define hash_filterfile                 250887266ul /**< "filterfile" */
425 #define hash_forward                      2029845ul /**< "forward" */
426 #define hash_forward_socks4            3963965521ul /**< "forward-socks4" */
427 #define hash_forward_socks4a           2639958518ul /**< "forward-socks4a" */
428 #define hash_jarfile                      2046641ul /**< "jarfile" */
429 #define hash_listen_address            1255650842ul /**< "listen-address" */
430 #define hash_logdir                        422889ul /**< "logdir" */
431 #define hash_logfile                      2114766ul /**< "logfile" */
432 #define hash_permit_access             3587953268ul /**< "permit-access" */
433 #define hash_proxy_info_url            3903079059ul /**< "proxy-info-url" */
434 #define hash_single_threaded           4250084780ul /**< "single-threaded" */
435 #define hash_suppress_blocklists       1948693308ul /**< "suppress-blocklists" */
436 #define hash_toggle                        447966ul /**< "toggle" */
437 #define hash_trust_info_url             430331967ul /**< "trust-info-url" */
438 #define hash_trustfile                   56494766ul /**< "trustfile" */
439 #define hash_usermanual                1416668518ul /**< "user-manual" */
440
441 #define hash_activity_animation        1817904738ul /**< "activity-animation" */
442 #define hash_close_button_minimizes    3651284693ul /**< "close-button-minimizes" */
443 #define hash_hide_console              2048809870ul /**< "hide-console" */
444 #define hash_log_buffer_size           2918070425ul /**< "log-buffer-size" */
445 #define hash_log_font_name             2866730124ul /**< "log-font-name" */
446 #define hash_log_font_size             2866731014ul /**< "log-font-size" */
447 #define hash_log_highlight_messages    4032101240ul /**< "log-highlight-messages" */
448 #define hash_log_max_lines             2868344173ul /**< "log-max-lines" */
449 #define hash_log_messages              2291744899ul /**< "log-messages" */
450 #define hash_show_on_task_bar           215410365ul /**< "show-on-task-bar" */
451
452
453 static void savearg(char *command, char *argument, struct configuration_spec * config);
454
455 /*********************************************************************
456  *
457  * Function    :  unload_configfile
458  *
459  * Description :  Free the config structure and all components.
460  *
461  * Parameters  :
462  *          1  :  data: struct configuration_spec to unload
463  *
464  * Returns     :  N/A
465  *
466  *********************************************************************/
467 void unload_configfile (void * data)
468 {
469    struct configuration_spec * config = (struct configuration_spec *)data;
470    struct forward_spec *cur_fwd = config->forward;
471 #ifdef FEATURE_ACL
472    struct access_control_list *cur_acl = config->acl;
473    int i;
474
475    while (cur_acl != NULL)
476    {
477       struct access_control_list * next_acl = cur_acl->next;
478       free(cur_acl);
479       cur_acl = next_acl;
480    }
481    config->acl = NULL;
482 #endif /* def FEATURE_ACL */
483
484    while (cur_fwd != NULL)
485    {
486       struct forward_spec * next_fwd = cur_fwd->next;
487       free_url_spec(cur_fwd->url);
488
489       freez(cur_fwd->gateway_host);
490       freez(cur_fwd->forward_host);
491       free(cur_fwd);
492       cur_fwd = next_fwd;
493    }
494    config->forward = NULL;
495
496 #ifdef FEATURE_COOKIE_JAR
497    if ( NULL != config->jar )
498    {
499       fclose( config->jar );
500       config->jar = NULL;
501    }
502 #endif /* def FEATURE_COOKIE_JAR */
503
504    freez(config->confdir);
505    freez(config->logdir);
506
507    freez(config->haddr);
508    freez(config->logfile);
509
510    for (i = 0; i < MAX_ACTION_FILES; i++)
511    {
512       freez(config->actions_file_short[i]);
513       freez(config->actions_file[i]);
514    }
515
516    freez(config->admin_address);
517    freez(config->proxy_info_url);
518    freez(config->proxy_args);
519    freez(config->usermanual);
520
521 #ifdef FEATURE_COOKIE_JAR
522    freez(config->jarfile);
523 #endif /* def FEATURE_COOKIE_JAR */
524
525    freez(config->re_filterfile);
526
527 }
528
529
530 #ifdef FEATURE_GRACEFUL_TERMINATION
531 /*********************************************************************
532  *
533  * Function    :  unload_current_config_file
534  *
535  * Description :  Unloads current config file - reset to state at
536  *                beginning of program.
537  *
538  * Parameters  :  None
539  *
540  * Returns     :  N/A
541  *
542  *********************************************************************/
543 void unload_current_config_file(void)
544 {
545    if (current_configfile)
546    {
547       current_configfile->unloader = unload_configfile;
548       current_configfile = NULL;
549    }
550 }
551 #endif
552
553
554 /*********************************************************************
555  *
556  * Function    :  load_config
557  *
558  * Description :  Load the config file and all parameters.
559  *
560  * Parameters  :  None
561  *
562  * Returns     :  The configuration_spec, or NULL on error.
563  *
564  *********************************************************************/
565 struct configuration_spec * load_config(void)
566 {
567    char buf[BUFFER_SIZE];
568    char *p, *q;
569    FILE *configfp = NULL;
570    struct configuration_spec * config = NULL;
571    struct client_state * fake_csp;
572    struct file_list *fs;
573    unsigned long linenum = 0;
574    int i;
575
576    if ( !check_file_changed(current_configfile, configfile, &fs))
577    {
578       /* No need to load */
579       return ((struct configuration_spec *)current_configfile->f);
580    }
581    if (!fs)
582    {
583       log_error(LOG_LEVEL_FATAL, "can't check configuration file '%s':  %E",
584                 configfile);
585    }
586
587    log_error(LOG_LEVEL_INFO, "loading configuration file '%s':", configfile);
588
589 #ifdef FEATURE_TOGGLE
590    g_bToggleIJB      = 1;
591 #endif /* def FEATURE_TOGGLE */
592
593    fs->f = config = (struct configuration_spec *)zalloc(sizeof(*config));
594
595    if (config==NULL)
596    {
597       freez(fs->filename);
598       freez(fs);
599       log_error(LOG_LEVEL_FATAL, "can't allocate memory for configuration");
600       /* Never get here - LOG_LEVEL_FATAL causes program exit */
601    }
602
603    /*
604     * This is backwards from how it's usually done.
605     * Following the usual pattern, "fs" would be stored in a member
606     * variable in "csp", and then we'd access "config" from "fs->f",
607     * using a cast.  However, "config" is used so often that a
608     * cast each time would be very ugly, and the extra indirection
609     * would waste CPU cycles.  Therefore we store "config" in
610     * "csp->config", and "fs" in "csp->config->config_file_list".
611     */
612    config->config_file_list = fs;
613
614    /*
615     * Set to defaults
616     */
617    config->multi_threaded    = 1;
618    config->hport             = HADDR_PORT;
619    config->buffer_limit      = 4096 * 1024;
620    config->usermanual        = strdup(USER_MANUAL_URL);
621    config->proxy_args        = strdup("");
622
623    if ((configfp = fopen(configfile, "r")) == NULL)
624    {
625       log_error(LOG_LEVEL_FATAL, "can't open configuration file '%s':  %E",
626               configfile);
627       /* Never get here - LOG_LEVEL_FATAL causes program exit */
628    }
629
630    while (read_config_line(buf, sizeof(buf), configfp, &linenum) != NULL)
631    {
632       char cmd[BUFFER_SIZE];
633       char arg[BUFFER_SIZE];
634       char tmp[BUFFER_SIZE];
635 #ifdef FEATURE_ACL
636       struct access_control_list *cur_acl;
637 #endif /* def FEATURE_ACL */
638       struct forward_spec *cur_fwd;
639       int vec_count;
640       char *vec[3];
641
642       strcpy(tmp, buf);
643
644       /* Copy command (i.e. up to space or tab) into cmd */
645       p = buf;
646       q = cmd;
647       while (*p && (*p != ' ') && (*p != '\t'))
648       {
649          *q++ = *p++;
650       }
651       *q = '\0';
652
653       /* Skip over the whitespace in buf */
654       while (*p && ((*p == ' ') || (*p == '\t')))
655       {
656          p++;
657       }
658
659       /* Copy the argument into arg */
660       strcpy(arg, p);
661
662       /* Should never happen, but check this anyway */
663       if (*cmd == '\0')
664       {
665          continue;
666       }
667
668       /* Make sure the command field is lower case */
669       for (p=cmd; *p; p++)
670       {
671          if (ijb_isupper(*p))
672          {
673             *p = ijb_tolower(*p);
674          }
675       }
676
677       /* Save the argument for show-proxy-args */
678       savearg(cmd, arg, config);
679
680
681       switch( hash_string( cmd ) )
682       {
683 /* *************************************************************************
684  * actionsfile actions-file-name
685  * In confdir by default
686  * *************************************************************************/
687          case hash_actions_file :
688             i = 0;
689             while ((i < MAX_ACTION_FILES) && (NULL != config->actions_file[i]))
690             {
691                i++;
692             }
693
694             if (i >= MAX_ACTION_FILES)
695             {
696                log_error(LOG_LEVEL_FATAL, "Too many 'actionsfile' directives in config file - limit is %d.\n"
697                   "(You can increase this limit by changing MAX_ACTION_FILES in project.h and recompiling).",
698                   MAX_ACTION_FILES);
699             }
700             config->actions_file_short[i] = strdup(arg);
701             p = malloc(strlen(arg) + sizeof(".action"));
702             if (p == NULL)
703             {
704                log_error(LOG_LEVEL_FATAL, "Out of memory");
705             }
706             strcpy(p, arg);
707             strcat(p, ".action");
708             config->actions_file[i] = make_path(config->confdir, p);
709             free(p);
710             continue;
711
712 /* *************************************************************************
713  * admin-address email-address
714  * *************************************************************************/
715          case hash_admin_address :
716             freez(config->admin_address);
717             config->admin_address = strdup(arg);
718             continue;
719
720 /* *************************************************************************
721  * buffer-limit n
722  * *************************************************************************/
723          case hash_buffer_limit :
724             config->buffer_limit = (size_t) 1024 * atoi(arg);
725             continue;
726
727 /* *************************************************************************
728  * confdir directory-name
729  * *************************************************************************/
730          case hash_confdir :
731             freez(config->confdir);
732             config->confdir = make_path( NULL, arg);
733             continue;
734
735 /* *************************************************************************
736  * debug n
737  * Specifies debug level, multiple values are ORed together.
738  * *************************************************************************/
739          case hash_debug :
740             config->debug |= atoi(arg);
741             continue;
742
743 /* *************************************************************************
744  * deny-access source-ip[/significant-bits] [dest-ip[/significant-bits]]
745  * *************************************************************************/
746 #ifdef FEATURE_ACL
747          case hash_deny_access:
748             vec_count = ssplit(arg, " \t", vec, SZ(vec), 1, 1);
749
750             if ((vec_count != 1) && (vec_count != 2))
751             {
752                log_error(LOG_LEVEL_ERROR, "Wrong number of parameters for "
753                      "deny-access directive in configuration file.");
754                string_append(&config->proxy_args,
755                   "<br>\nWARNING: Wrong number of parameters for "
756                   "deny-access directive in configuration file.<br><br>\n");
757                continue;
758             }
759
760             /* allocate a new node */
761             cur_acl = (struct access_control_list *) zalloc(sizeof(*cur_acl));
762
763             if (cur_acl == NULL)
764             {
765                log_error(LOG_LEVEL_FATAL, "can't allocate memory for configuration");
766                /* Never get here - LOG_LEVEL_FATAL causes program exit */
767                continue;
768             }
769             cur_acl->action = ACL_DENY;
770
771             if (acl_addr(vec[0], cur_acl->src) < 0)
772             {
773                log_error(LOG_LEVEL_ERROR, "Invalid source IP for deny-access "
774                      "directive in configuration file: \"%s\"", vec[0]);
775                string_append(&config->proxy_args,
776                   "<br>\nWARNING: Invalid source IP for deny-access directive"
777                   " in configuration file: \"");
778                string_append(&config->proxy_args,
779                   vec[0]);
780                string_append(&config->proxy_args,
781                   "\"<br><br>\n");
782                freez(cur_acl);
783                continue;
784             }
785             if (vec_count == 2)
786             {
787                if (acl_addr(vec[1], cur_acl->dst) < 0)
788                {
789                   log_error(LOG_LEVEL_ERROR, "Invalid destination IP for deny-access "
790                         "directive in configuration file: \"%s\"", vec[0]);
791                   string_append(&config->proxy_args,
792                      "<br>\nWARNING: Invalid destination IP for deny-access directive"
793                      " in configuration file: \"");
794                   string_append(&config->proxy_args,
795                      vec[0]);
796                   string_append(&config->proxy_args,
797                      "\"<br><br>\n");
798                   freez(cur_acl);
799                   continue;
800                }
801             }
802
803             /*
804              * Add it to the list.  Note we reverse the list to get the
805              * behaviour the user expects.  With both the ACL and
806              * actions file, the last match wins.  However, the internal
807              * implementations are different:  The actions file is stored
808              * in the same order as the file, and scanned completely.
809              * With the ACL, we reverse the order as we load it, then
810              * when we scan it we stop as soon as we get a match.
811              */
812             cur_acl->next  = config->acl;
813             config->acl = cur_acl;
814
815             continue;
816 #endif /* def FEATURE_ACL */
817
818 /* *************************************************************************
819  * enable-edit-actions 0|1
820  * *************************************************************************/
821 #ifdef FEATURE_CGI_EDIT_ACTIONS
822          case hash_enable_edit_actions:
823             if ((*arg != '\0') && (0 != atoi(arg)))
824             {
825                config->feature_flags |= RUNTIME_FEATURE_CGI_EDIT_ACTIONS;
826             }
827             else
828             {
829                config->feature_flags &= ~RUNTIME_FEATURE_CGI_EDIT_ACTIONS;
830             }
831             continue;
832 #endif /* def FEATURE_CGI_EDIT_ACTIONS */
833
834 /* *************************************************************************
835  * enable-remote-toggle 0|1
836  * *************************************************************************/
837 #ifdef FEATURE_CGI_EDIT_ACTIONS
838          case hash_enable_remote_toggle:
839             if ((*arg != '\0') && (0 != atoi(arg)))
840             {
841                config->feature_flags |= RUNTIME_FEATURE_CGI_TOGGLE;
842             }
843             else
844             {
845                config->feature_flags &= ~RUNTIME_FEATURE_CGI_TOGGLE;
846             }
847             continue;
848 #endif /* def FEATURE_CGI_EDIT_ACTIONS */
849
850 /* *************************************************************************
851  * forward url-pattern (.|http-proxy-host[:port])
852  * *************************************************************************/
853          case hash_forward:
854             vec_count = ssplit(arg, " \t", vec, SZ(vec), 1, 1);
855
856             if (vec_count != 2)
857             {
858                log_error(LOG_LEVEL_ERROR, "Wrong number of parameters for forward "
859                      "directive in configuration file.");
860                string_append(&config->proxy_args,
861                   "<br>\nWARNING: Wrong number of parameters for "
862                   "forward directive in configuration file.");
863                continue;
864             }
865
866             /* allocate a new node */
867             cur_fwd = zalloc(sizeof(*cur_fwd));
868             if (cur_fwd == NULL)
869             {
870                log_error(LOG_LEVEL_FATAL, "can't allocate memory for configuration");
871                /* Never get here - LOG_LEVEL_FATAL causes program exit */
872                continue;
873             }
874
875             cur_fwd->type = SOCKS_NONE;
876
877             /* Save the URL pattern */
878             if (create_url_spec(cur_fwd->url, vec[0]))
879             {
880                log_error(LOG_LEVEL_ERROR, "Bad URL specifier for forward "
881                      "directive in configuration file.");
882                string_append(&config->proxy_args,
883                   "<br>\nWARNING: Bad URL specifier for "
884                   "forward directive in configuration file.");
885                continue;
886             }
887
888             /* Parse the parent HTTP proxy host:port */
889             p = vec[1];
890
891             if (strcmp(p, ".") != 0)
892             {
893                cur_fwd->forward_host = strdup(p);
894
895                if (NULL != (p = strchr(cur_fwd->forward_host, ':')))
896                {
897                   *p++ = '\0';
898                   cur_fwd->forward_port = atoi(p);
899                }
900
901                if (cur_fwd->forward_port <= 0)
902                {
903                   cur_fwd->forward_port = 8000;
904                }
905             }
906
907             /* Add to list. */
908             cur_fwd->next = config->forward;
909             config->forward = cur_fwd;
910
911             continue;
912
913 /* *************************************************************************
914  * forward-socks4 url-pattern socks-proxy[:port] (.|http-proxy[:port])
915  * *************************************************************************/
916          case hash_forward_socks4:
917             vec_count = ssplit(arg, " \t", vec, SZ(vec), 1, 1);
918
919             if (vec_count != 3)
920             {
921                log_error(LOG_LEVEL_ERROR, "Wrong number of parameters for "
922                      "forward-socks4 directive in configuration file.");
923                string_append(&config->proxy_args,
924                   "<br>\nWARNING: Wrong number of parameters for "
925                   "forward-socks4 directive in configuration file.");
926                continue;
927             }
928
929             /* allocate a new node */
930             cur_fwd = zalloc(sizeof(*cur_fwd));
931             if (cur_fwd == NULL)
932             {
933                log_error(LOG_LEVEL_FATAL, "can't allocate memory for configuration");
934                /* Never get here - LOG_LEVEL_FATAL causes program exit */
935                continue;
936             }
937
938             cur_fwd->type = SOCKS_4;
939
940             /* Save the URL pattern */
941             if (create_url_spec(cur_fwd->url, vec[0]))
942             {
943                log_error(LOG_LEVEL_ERROR, "Bad URL specifier for forward-socks4 "
944                      "directive in configuration file.");
945                string_append(&config->proxy_args,
946                   "<br>\nWARNING: Bad URL specifier for "
947                   "forward-socks4 directive in configuration file.");
948                continue;
949             }
950
951             /* Parse the SOCKS proxy host[:port] */
952             p = vec[1];
953
954             if (strcmp(p, ".") != 0)
955             {
956                cur_fwd->gateway_host = strdup(p);
957
958                if (NULL != (p = strchr(cur_fwd->gateway_host, ':')))
959                {
960                   *p++ = '\0';
961                   cur_fwd->gateway_port = atoi(p);
962                }
963                if (cur_fwd->gateway_port <= 0)
964                {
965                   cur_fwd->gateway_port = 1080;
966                }
967             }
968
969             /* Parse the parent HTTP proxy host[:port] */
970             p = vec[2];
971
972             if (strcmp(p, ".") != 0)
973             {
974                cur_fwd->forward_host = strdup(p);
975
976                if (NULL != (p = strchr(cur_fwd->forward_host, ':')))
977                {
978                   *p++ = '\0';
979                   cur_fwd->forward_port = atoi(p);
980                }
981
982                if (cur_fwd->forward_port <= 0)
983                {
984                   cur_fwd->forward_port = 8000;
985                }
986             }
987
988             /* Add to list. */
989             cur_fwd->next = config->forward;
990             config->forward = cur_fwd;
991
992             continue;
993
994 /* *************************************************************************
995  * forward-socks4a url-pattern socks-proxy[:port] (.|http-proxy[:port])
996  * *************************************************************************/
997          case hash_forward_socks4a:
998             vec_count = ssplit(arg, " \t", vec, SZ(vec), 1, 1);
999
1000             if (vec_count != 3)
1001             {
1002                log_error(LOG_LEVEL_ERROR, "Wrong number of parameters for "
1003                      "forward-socks4a directive in configuration file.");
1004                string_append(&config->proxy_args,
1005                   "<br>\nWARNING: Wrong number of parameters for "
1006                   "forward-socks4a directive in configuration file.");
1007                continue;
1008             }
1009
1010             /* allocate a new node */
1011             cur_fwd = zalloc(sizeof(*cur_fwd));
1012             if (cur_fwd == NULL)
1013             {
1014                log_error(LOG_LEVEL_FATAL, "can't allocate memory for configuration");
1015                /* Never get here - LOG_LEVEL_FATAL causes program exit */
1016                continue;
1017             }
1018
1019             cur_fwd->type = SOCKS_4A;
1020
1021             /* Save the URL pattern */
1022             if (create_url_spec(cur_fwd->url, vec[0]))
1023             {
1024                log_error(LOG_LEVEL_ERROR, "Bad URL specifier for forward-socks4a "
1025                      "directive in configuration file.");
1026                string_append(&config->proxy_args,
1027                   "<br>\nWARNING: Bad URL specifier for "
1028                   "forward-socks4a directive in configuration file.");
1029                continue;
1030             }
1031
1032             /* Parse the SOCKS proxy host[:port] */
1033             p = vec[1];
1034
1035             cur_fwd->gateway_host = strdup(p);
1036
1037             if (NULL != (p = strchr(cur_fwd->gateway_host, ':')))
1038             {
1039                *p++ = '\0';
1040                cur_fwd->gateway_port = atoi(p);
1041             }
1042             if (cur_fwd->gateway_port <= 0)
1043             {
1044                cur_fwd->gateway_port = 1080;
1045             }
1046
1047             /* Parse the parent HTTP proxy host[:port] */
1048             p = vec[2];
1049
1050             if (strcmp(p, ".") != 0)
1051             {
1052                cur_fwd->forward_host = strdup(p);
1053
1054                if (NULL != (p = strchr(cur_fwd->forward_host, ':')))
1055                {
1056                   *p++ = '\0';
1057                   cur_fwd->forward_port = atoi(p);
1058                }
1059
1060                if (cur_fwd->forward_port <= 0)
1061                {
1062                   cur_fwd->forward_port = 8000;
1063                }
1064             }
1065
1066             /* Add to list. */
1067             cur_fwd->next = config->forward;
1068             config->forward = cur_fwd;
1069
1070             continue;
1071
1072 /* *************************************************************************
1073  * jarfile jar-file-name
1074  * In logdir by default
1075  * *************************************************************************/
1076 #ifdef FEATURE_COOKIE_JAR
1077          case hash_jarfile :
1078             freez(config->jarfile);
1079             config->jarfile = make_path(config->logdir, arg);
1080             continue;
1081 #endif /* def FEATURE_COOKIE_JAR */
1082
1083 /* *************************************************************************
1084  * listen-address [ip][:port]
1085  * *************************************************************************/
1086          case hash_listen_address :
1087             freez(config->haddr);
1088             config->haddr = strdup(arg);
1089             continue;
1090
1091 /* *************************************************************************
1092  * logdir directory-name
1093  * *************************************************************************/
1094          case hash_logdir :
1095             freez(config->logdir);
1096             config->logdir = make_path(NULL, arg);
1097             continue;
1098
1099 /* *************************************************************************
1100  * logfile log-file-name
1101  * In logdir by default
1102  * *************************************************************************/
1103          case hash_logfile :
1104             freez(config->logfile);
1105             config->logfile = no_daemon ? NULL : make_path(config->logdir, arg);
1106             continue;
1107
1108 /* *************************************************************************
1109  * permit-access source-ip[/significant-bits] [dest-ip[/significant-bits]]
1110  * *************************************************************************/
1111 #ifdef FEATURE_ACL
1112          case hash_permit_access:
1113             vec_count = ssplit(arg, " \t", vec, SZ(vec), 1, 1);
1114
1115             if ((vec_count != 1) && (vec_count != 2))
1116             {
1117                log_error(LOG_LEVEL_ERROR, "Wrong number of parameters for "
1118                      "permit-access directive in configuration file.");
1119                string_append(&config->proxy_args,
1120                   "<br>\nWARNING: Wrong number of parameters for "
1121                   "permit-access directive in configuration file.<br><br>\n");
1122
1123                continue;
1124             }
1125
1126             /* allocate a new node */
1127             cur_acl = (struct access_control_list *) zalloc(sizeof(*cur_acl));
1128
1129             if (cur_acl == NULL)
1130             {
1131                log_error(LOG_LEVEL_FATAL, "can't allocate memory for configuration");
1132                /* Never get here - LOG_LEVEL_FATAL causes program exit */
1133                continue;
1134             }
1135             cur_acl->action = ACL_PERMIT;
1136
1137             if (acl_addr(vec[0], cur_acl->src) < 0)
1138             {
1139                log_error(LOG_LEVEL_ERROR, "Invalid source IP for permit-access "
1140                      "directive in configuration file: \"%s\"", vec[0]);
1141                string_append(&config->proxy_args,
1142                   "<br>\nWARNING: Invalid source IP for permit-access directive"
1143                   " in configuration file: \"");
1144                string_append(&config->proxy_args,
1145                   vec[0]);
1146                string_append(&config->proxy_args,
1147                   "\"<br><br>\n");
1148                freez(cur_acl);
1149                continue;
1150             }
1151             if (vec_count == 2)
1152             {
1153                if (acl_addr(vec[1], cur_acl->dst) < 0)
1154                {
1155                   log_error(LOG_LEVEL_ERROR, "Invalid destination IP for "
1156                         "permit-access directive in configuration file: \"%s\"",
1157                         vec[0]);
1158                   string_append(&config->proxy_args,
1159                      "<br>\nWARNING: Invalid destination IP for permit-access directive"
1160                      " in configuration file: \"");
1161                   string_append(&config->proxy_args,
1162                      vec[0]);
1163                   string_append(&config->proxy_args,
1164                      "\"<br><br>\n");
1165                   freez(cur_acl);
1166                   continue;
1167                }
1168             }
1169
1170             /*
1171              * Add it to the list.  Note we reverse the list to get the
1172              * behaviour the user expects.  With both the ACL and
1173              * actions file, the last match wins.  However, the internal
1174              * implementations are different:  The actions file is stored
1175              * in the same order as the file, and scanned completely.
1176              * With the ACL, we reverse the order as we load it, then
1177              * when we scan it we stop as soon as we get a match.
1178              */
1179             cur_acl->next  = config->acl;
1180             config->acl = cur_acl;
1181
1182             continue;
1183 #endif /* def FEATURE_ACL */
1184
1185 /* *************************************************************************
1186  * proxy-info-url url
1187  * *************************************************************************/
1188          case hash_proxy_info_url :
1189             freez(config->proxy_info_url);
1190             config->proxy_info_url = strdup(arg);
1191             continue;
1192
1193 /* *************************************************************************
1194  * re_filterfile file-name
1195  * In confdir by default.
1196  * *************************************************************************/
1197          case hash_filterfile :
1198             freez(config->re_filterfile);
1199             config->re_filterfile = make_path(config->confdir, arg);
1200             continue;
1201
1202 /* *************************************************************************
1203  * single-threaded
1204  * *************************************************************************/
1205          case hash_single_threaded :
1206             config->multi_threaded = 0;
1207             continue;
1208
1209 /* *************************************************************************
1210  * toggle (0|1)
1211  * *************************************************************************/
1212 #ifdef FEATURE_TOGGLE
1213          case hash_toggle :
1214             g_bToggleIJB = atoi(arg);
1215             continue;
1216 #endif /* def FEATURE_TOGGLE */
1217
1218 /* *************************************************************************
1219  * trust-info-url url
1220  * *************************************************************************/
1221 #ifdef FEATURE_TRUST
1222          case hash_trust_info_url :
1223             enlist(config->trust_info, arg);
1224             continue;
1225 #endif /* def FEATURE_TRUST */
1226
1227 /* *************************************************************************
1228  * trustfile filename
1229  * (In confdir by default.)
1230  * *************************************************************************/
1231 #ifdef FEATURE_TRUST
1232          case hash_trustfile :
1233             freez(config->trustfile);
1234             config->trustfile = make_path(config->confdir, arg);
1235             continue;
1236 #endif /* def FEATURE_TRUST */
1237
1238 /* *************************************************************************
1239  * usermanual url
1240  * *************************************************************************/
1241          case hash_usermanual :
1242             freez(config->usermanual);
1243             config->usermanual = strdup(arg);
1244             continue;
1245
1246 /* *************************************************************************
1247  * Win32 Console options:
1248  * *************************************************************************/
1249
1250 /* *************************************************************************
1251  * hide-console
1252  * *************************************************************************/
1253 #ifdef _WIN_CONSOLE
1254          case hash_hide_console :
1255             hideConsole = 1;
1256             continue;
1257 #endif /*def _WIN_CONSOLE*/
1258
1259
1260 /* *************************************************************************
1261  * Win32 GUI options:
1262  * *************************************************************************/
1263
1264 #if defined(_WIN32) && ! defined(_WIN_CONSOLE)
1265 /* *************************************************************************
1266  * activity-animation (0|1)
1267  * *************************************************************************/
1268          case hash_activity_animation :
1269             g_bShowActivityAnimation = atoi(arg);
1270             continue;
1271
1272 /* *************************************************************************
1273  *  close-button-minimizes (0|1)
1274  * *************************************************************************/
1275          case hash_close_button_minimizes :
1276             g_bCloseHidesWindow = atoi(arg);
1277             continue;
1278
1279 /* *************************************************************************
1280  * log-buffer-size (0|1)
1281  * *************************************************************************/
1282          case hash_log_buffer_size :
1283             g_bLimitBufferSize = atoi(arg);
1284             continue;
1285
1286 /* *************************************************************************
1287  * log-font-name fontnane
1288  * *************************************************************************/
1289          case hash_log_font_name :
1290             strcpy( g_szFontFaceName, arg );
1291             continue;
1292
1293 /* *************************************************************************
1294  * log-font-size n
1295  * *************************************************************************/
1296          case hash_log_font_size :
1297             g_nFontSize = atoi(arg);
1298             continue;
1299
1300 /* *************************************************************************
1301  * log-highlight-messages (0|1)
1302  * *************************************************************************/
1303          case hash_log_highlight_messages :
1304             g_bHighlightMessages = atoi(arg);
1305             continue;
1306
1307 /* *************************************************************************
1308  * log-max-lines n
1309  * *************************************************************************/
1310          case hash_log_max_lines :
1311             g_nMaxBufferLines = atoi(arg);
1312             continue;
1313
1314 /* *************************************************************************
1315  * log-messages (0|1)
1316  * *************************************************************************/
1317          case hash_log_messages :
1318             g_bLogMessages = atoi(arg);
1319             continue;
1320
1321 /* *************************************************************************
1322  * show-on-task-bar (0|1)
1323  * *************************************************************************/
1324          case hash_show_on_task_bar :
1325             g_bShowOnTaskBar = atoi(arg);
1326             continue;
1327
1328 #endif /* defined(_WIN32) && ! defined(_WIN_CONSOLE) */
1329
1330
1331 /* *************************************************************************
1332  * Warnings about unsupported features
1333  * *************************************************************************/
1334 #ifndef FEATURE_ACL
1335          case hash_deny_access:
1336 #endif /* ndef FEATURE_ACL */
1337 #ifndef FEATURE_CGI_EDIT_ACTIONS
1338          case hash_enable_edit_actions:
1339          case hash_enable_remote_toggle:
1340 #endif /* def FEATURE_CGI_EDIT_ACTIONS */
1341 #ifndef FEATURE_COOKIE_JAR
1342          case hash_jarfile :
1343 #endif /* ndef FEATURE_COOKIE_JAR */
1344 #ifndef FEATURE_ACL
1345          case hash_permit_access:
1346 #endif /* ndef FEATURE_ACL */
1347 #ifndef FEATURE_TOGGLE
1348          case hash_toggle :
1349 #endif /* ndef FEATURE_TOGGLE */
1350 #ifndef FEATURE_TRUST
1351          case hash_trustfile :
1352          case hash_trust_info_url :
1353 #endif /* ndef FEATURE_TRUST */
1354
1355 #ifndef _WIN_CONSOLE
1356          case hash_hide_console :
1357 #endif /* ndef _WIN_CONSOLE */
1358
1359 #if defined(_WIN_CONSOLE) || ! defined(_WIN32)
1360          case hash_activity_animation :
1361          case hash_close_button_minimizes :
1362          case hash_log_buffer_size :
1363          case hash_log_font_name :
1364          case hash_log_font_size :
1365          case hash_log_highlight_messages :
1366          case hash_log_max_lines :
1367          case hash_log_messages :
1368          case hash_show_on_task_bar :
1369 #endif /* defined(_WIN_CONSOLE) || ! defined(_WIN32) */
1370             /* These warnings are annoying - so hide them. -- Jon */
1371             /* log_error(LOG_LEVEL_INFO, "Unsupported directive \"%s\" ignored.", cmd); */
1372             continue;
1373
1374 /* *************************************************************************/
1375          default :
1376 /* *************************************************************************/
1377             /*
1378              * I decided that I liked this better as a warning than an
1379              * error.  To change back to an error, just change log level
1380              * to LOG_LEVEL_FATAL.
1381              */
1382             log_error(LOG_LEVEL_ERROR, "Unrecognized directive '%s' (%luul) in line %lu in "
1383                   "configuration file (%s).",  buf, hash_string(cmd), linenum, configfile);
1384             string_append(&config->proxy_args, "<br>\nWARNING: unrecognized directive : ");
1385             string_append(&config->proxy_args, buf);
1386             string_append(&config->proxy_args, "<br><br>\n");
1387             continue;
1388
1389 /* *************************************************************************/
1390       } /* end switch( hash_string(cmd) ) */
1391    } /* end while ( read_config_line(...) ) */
1392
1393    fclose(configfp);
1394
1395    if (NULL == config->proxy_args)
1396    {
1397       log_error(LOG_LEVEL_FATAL, "Out of memory loading config - insufficient memory for config->proxy_args");
1398    }
1399
1400    init_error_log(Argv[0], config->logfile, config->debug);
1401
1402    if (config->actions_file[0])
1403    {
1404       add_loader(load_actions_file, config);
1405    }
1406
1407    if (config->re_filterfile)
1408    {
1409       add_loader(load_re_filterfile, config);
1410    }
1411
1412 #ifdef FEATURE_TRUST
1413    if (config->trustfile)
1414    {
1415       add_loader(load_trustfile, config);
1416    }
1417 #endif /* def FEATURE_TRUST */
1418
1419 #ifdef FEATURE_COOKIE_JAR
1420    if ( NULL != config->jarfile )
1421    {
1422       if ( NULL == (config->jar = fopen(config->jarfile, "a")) )
1423       {
1424          log_error(LOG_LEVEL_FATAL, "can't open jarfile '%s': %E", config->jarfile);
1425          /* Never get here - LOG_LEVEL_FATAL causes program exit */
1426       }
1427       setbuf(config->jar, NULL);
1428    }
1429 #endif /* def FEATURE_COOKIE_JAR */
1430
1431    if ( NULL == config->haddr )
1432    {
1433       config->haddr = strdup( HADDR_DEFAULT );
1434    }
1435
1436    if ( NULL != config->haddr )
1437    {
1438       if (NULL != (p = strchr(config->haddr, ':')))
1439       {
1440          *p++ = '\0';
1441          if (*p)
1442          {
1443             config->hport = atoi(p);
1444          }
1445       }
1446
1447       if (config->hport <= 0)
1448       {
1449          *--p = ':';
1450          log_error(LOG_LEVEL_FATAL, "invalid bind port spec %s", config->haddr);
1451          /* Never get here - LOG_LEVEL_FATAL causes program exit */
1452       }
1453       if (*config->haddr == '\0')
1454       {
1455          config->haddr = NULL;
1456       }
1457    }
1458
1459    /*
1460     * Want to run all the loaders once now.
1461     *
1462     * Need to set up a fake csp, so they can get to the config.
1463     */
1464    fake_csp = (struct client_state *) zalloc (sizeof(*fake_csp));
1465    fake_csp->config = config;
1466
1467    if (run_loader(fake_csp))
1468    {
1469       freez(fake_csp);
1470       log_error(LOG_LEVEL_FATAL, "A loader failed while loading config file. Exiting.");
1471       /* Never get here - LOG_LEVEL_FATAL causes program exit */
1472    }
1473    freez(fake_csp);
1474
1475 /* FIXME: this is a kludge for win32 */
1476 #if defined(_WIN32) && !defined (_WIN_CONSOLE)
1477
1478    g_actions_file     = config->actions_file[0]; /* FIXME only works for first action file */
1479    g_re_filterfile    = config->re_filterfile;
1480
1481 #ifdef FEATURE_TRUST
1482    g_trustfile        = config->trustfile;
1483 #endif /* def FEATURE_TRUST */
1484
1485
1486 #endif /* defined(_WIN32) && !defined (_WIN_CONSOLE) */
1487 /* FIXME: end kludge */
1488
1489
1490    config->need_bind = 1;
1491
1492    if (current_configfile)
1493    {
1494       struct configuration_spec * oldcfg = (struct configuration_spec *)
1495                                            current_configfile->f;
1496       /*
1497        * Check if config->haddr,hport == oldcfg->haddr,hport
1498        *
1499        * The following could be written more compactly as a single,
1500        * (unreadably long) if statement.
1501        */
1502       config->need_bind = 0;
1503       if (config->hport != oldcfg->hport)
1504       {
1505          config->need_bind = 1;
1506       }
1507       else if (config->haddr == NULL)
1508       {
1509          if (oldcfg->haddr != NULL)
1510          {
1511             config->need_bind = 1;
1512          }
1513       }
1514       else if (oldcfg->haddr == NULL)
1515       {
1516          config->need_bind = 1;
1517       }
1518       else if (0 != strcmp(config->haddr, oldcfg->haddr))
1519       {
1520          config->need_bind = 1;
1521       }
1522
1523       current_configfile->unloader = unload_configfile;
1524    }
1525
1526    fs->next = files->next;
1527    files->next = fs;
1528
1529    current_configfile = fs;
1530
1531    return (config);
1532 }
1533
1534
1535 /*********************************************************************
1536  *
1537  * Function    :  savearg
1538  *
1539  * Description :  Called from `load_config'.  It saves each non-empty
1540  *                and non-comment line from config into
1541  *                config->proxy_args.  This is used to create the
1542  *                show-proxy-args page.  On error, frees
1543  *                config->proxy_args and sets it to NULL
1544  *
1545  * Parameters  :
1546  *          1  :  command = config setting that was found
1547  *          2  :  argument = the setting's argument (if any)
1548  *          3  :  config = Configuration to save into.
1549  *
1550  * Returns     :  N/A
1551  *
1552  *********************************************************************/
1553 static void savearg(char *command, char *argument, struct configuration_spec * config)
1554 {
1555    char * buf;
1556    char * s;
1557
1558    assert(command);
1559    assert(*command);
1560    assert(argument);
1561
1562    /*
1563     * Add config option name embedded in
1564     * link to it's section in the user-manual
1565     */
1566    buf = strdup("<a href=\"");
1567    string_append(&buf, config->usermanual);
1568    string_append(&buf, CONFIG_HELP_PREFIX);
1569    string_join  (&buf, string_toupper(command));
1570    string_append(&buf, "\">");
1571    string_append(&buf, command);
1572    string_append(&buf, "</a> ");
1573
1574    if (NULL == buf)
1575    {
1576       freez(config->proxy_args);
1577       return;
1578    }
1579
1580    if ( (NULL != argument) && ('\0' != *argument) )
1581    {
1582       s = html_encode(argument);
1583       if (NULL == s)
1584       {
1585          freez(buf);
1586          freez(config->proxy_args);
1587          return;
1588       }
1589
1590       if (strncmpic(argument, "http://", 7) == 0)
1591       {
1592          string_append(&buf, "<a href=\"");
1593          string_append(&buf, s);
1594          string_append(&buf, "\">");
1595          string_join  (&buf, s);
1596          string_append(&buf, "</a>");
1597       }
1598       else
1599       {
1600          string_join  (&buf, s);
1601       }
1602    }
1603
1604    string_append(&buf, "<br>\n");
1605
1606    string_join(&config->proxy_args, buf);
1607 }
1608
1609
1610 /*
1611   Local Variables:
1612   tab-width: 3
1613   end:
1614 */