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