Added Guy's last name
[privoxy.git] / loadcfg.c
1 const char loadcfg_rcs[] = "$Id: loadcfg.c,v 1.48.2.1 2002/08/21 17:58:05 oes 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.1  2002/08/21 17:58:05  oes
39  *    Temp kludge to let user and default action file be edited through win32 GUI (FR 592080)
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 /* by haroon - indicates if ijb is enabled */
376 int g_bToggleIJB        = 1;   /* Privoxy is enabled by default. */
377 #endif /* def FEATURE_TOGGLE */
378
379 /* The filename of the configfile */
380 const char *configfile  = NULL;
381
382 /*
383  * CGI functions will later need access to the invocation args,
384  * so we will make argc and argv global.
385  */
386 int Argc = 0;
387 const char **Argv = NULL;
388
389 static struct file_list *current_configfile = NULL;
390
391
392 /*
393  * This takes the "cryptic" hash of each keyword and aliases them to
394  * something a little more readable.  This also makes changing the
395  * hash values easier if they should change or the hash algorthm changes.
396  * Use the included "hash" program to find out what the hash will be
397  * for any string supplied on the command line.  (Or just put it in the
398  * config file and read the number from the error message in the log).
399  *
400  * Please keep this list sorted alphabetically (but with the Windows
401  * console and GUI specific options last).
402  */
403
404 #define hash_actions_file              1196306641ul /* "actionsfile" */
405 #define hash_admin_address             4112573064ul /* "admin-address" */
406 #define hash_buffer_limit              1881726070ul /* "buffer-limit */
407 #define hash_confdir                      1978389ul /* "confdir" */
408 #define hash_debug                          78263ul /* "debug" */
409 #define hash_deny_access               1227333715ul /* "deny-access" */
410 #define hash_enable_edit_actions       2517097536ul /* "enable-edit-actions" */
411 #define hash_enable_remote_toggle      2979744683ul /* "enable-remote-toggle" */
412 #define hash_filterfile                 250887266ul /* "filterfile" */
413 #define hash_forward                      2029845ul /* "forward" */
414 #define hash_forward_socks4            3963965521ul /* "forward-socks4" */
415 #define hash_forward_socks4a           2639958518ul /* "forward-socks4a" */
416 #define hash_jarfile                      2046641ul /* "jarfile" */
417 #define hash_listen_address            1255650842ul /* "listen-address" */
418 #define hash_logdir                        422889ul /* "logdir" */
419 #define hash_logfile                      2114766ul /* "logfile" */
420 #define hash_permit_access             3587953268ul /* "permit-access" */
421 #define hash_proxy_info_url            3903079059ul /* "proxy-info-url" */
422 #define hash_single_threaded           4250084780ul /* "single-threaded" */
423 #define hash_suppress_blocklists       1948693308ul /* "suppress-blocklists" */
424 #define hash_toggle                        447966ul /* "toggle" */
425 #define hash_trust_info_url             430331967ul /* "trust-info-url" */
426 #define hash_trustfile                   56494766ul /* "trustfile" */
427 #define hash_usermanual                1416668518ul /* "user-manual" */
428 #define hash_activity_animation        1817904738ul /* "activity-animation" */
429 #define hash_close_button_minimizes    3651284693ul /* "close-button-minimizes" */
430 #define hash_hide_console              2048809870ul /* "hide-console" */
431 #define hash_log_buffer_size           2918070425ul /* "log-buffer-size" */
432 #define hash_log_font_name             2866730124ul /* "log-font-name" */
433 #define hash_log_font_size             2866731014ul /* "log-font-size" */
434 #define hash_log_highlight_messages    4032101240ul /* "log-highlight-messages" */
435 #define hash_log_max_lines             2868344173ul /* "log-max-lines" */
436 #define hash_log_messages              2291744899ul /* "log-messages" */
437 #define hash_show_on_task_bar           215410365ul /* "show-on-task-bar" */
438
439
440 static void savearg(char *command, char *argument, struct configuration_spec * config);
441
442 /*********************************************************************
443  *
444  * Function    :  unload_configfile
445  *
446  * Description :  Free the config structure and all components.
447  *
448  * Parameters  :
449  *          1  :  data: struct configuration_spec to unload
450  *
451  * Returns     :  N/A
452  *
453  *********************************************************************/
454 void unload_configfile (void * data)
455 {
456    struct configuration_spec * config = (struct configuration_spec *)data;
457    struct forward_spec *cur_fwd = config->forward;
458    int i;
459
460 #ifdef FEATURE_ACL
461    struct access_control_list *cur_acl = config->acl;
462
463    while (cur_acl != NULL)
464    {
465       struct access_control_list * next_acl = cur_acl->next;
466       free(cur_acl);
467       cur_acl = next_acl;
468    }
469    config->acl = NULL;
470 #endif /* def FEATURE_ACL */
471
472    while (cur_fwd != NULL)
473    {
474       struct forward_spec * next_fwd = cur_fwd->next;
475       free_url_spec(cur_fwd->url);
476
477       freez(cur_fwd->gateway_host);
478       freez(cur_fwd->forward_host);
479       free(cur_fwd);
480       cur_fwd = next_fwd;
481    }
482    config->forward = NULL;
483
484 #ifdef FEATURE_COOKIE_JAR
485    if ( NULL != config->jar )
486    {
487       fclose( config->jar );
488       config->jar = NULL;
489    }
490 #endif /* def FEATURE_COOKIE_JAR */
491
492    freez(config->confdir);
493    freez(config->logdir);
494
495    freez(config->haddr);
496    freez(config->logfile);
497
498    for (i = 0; i < MAX_ACTION_FILES; i++)
499    {
500       freez(config->actions_file_short[i]);
501       freez(config->actions_file[i]);
502    }
503
504    freez(config->admin_address);
505    freez(config->proxy_info_url);
506    freez(config->proxy_args);
507    freez(config->usermanual);
508
509 #ifdef FEATURE_COOKIE_JAR
510    freez(config->jarfile);
511 #endif /* def FEATURE_COOKIE_JAR */
512
513    freez(config->re_filterfile);
514
515 }
516
517
518 #ifdef FEATURE_GRACEFUL_TERMINATION
519 /*********************************************************************
520  *
521  * Function    :  unload_current_config_file
522  *
523  * Description :  Unloads current config file - reset to state at
524  *                beginning of program.
525  *
526  * Parameters  :  None
527  *
528  * Returns     :  N/A
529  *
530  *********************************************************************/
531 void unload_current_config_file(void)
532 {
533    if (current_configfile)
534    {
535       current_configfile->unloader = unload_configfile;
536       current_configfile = NULL;
537    }
538 }
539 #endif
540
541
542 /*********************************************************************
543  *
544  * Function    :  load_config
545  *
546  * Description :  Load the config file and all parameters.
547  *
548  * Parameters  :  None
549  *
550  * Returns     :  The configuration_spec, or NULL on error.
551  *
552  *********************************************************************/
553 struct configuration_spec * load_config(void)
554 {
555    char buf[BUFFER_SIZE];
556    char *p, *q;
557    FILE *configfp = NULL;
558    struct configuration_spec * config = NULL;
559    struct client_state * fake_csp;
560    struct file_list *fs;
561    unsigned long linenum = 0;
562    int i;
563
564    if ( !check_file_changed(current_configfile, configfile, &fs))
565    {
566       /* No need to load */
567       return ((struct configuration_spec *)current_configfile->f);
568    }
569    if (!fs)
570    {
571       log_error(LOG_LEVEL_FATAL, "can't check configuration file '%s':  %E",
572                 configfile);
573    }
574
575    log_error(LOG_LEVEL_INFO, "loading configuration file '%s':", configfile);
576
577 #ifdef FEATURE_TOGGLE
578    g_bToggleIJB      = 1;
579 #endif /* def FEATURE_TOGGLE */
580
581    fs->f = config = (struct configuration_spec *)zalloc(sizeof(*config));
582
583    if (config==NULL)
584    {
585       freez(fs->filename);
586       freez(fs);
587       log_error(LOG_LEVEL_FATAL, "can't allocate memory for configuration");
588       /* Never get here - LOG_LEVEL_FATAL causes program exit */
589    }
590
591    /*
592     * This is backwards from how it's usually done.
593     * Following the usual pattern, "fs" would be stored in a member
594     * variable in "csp", and then we'd access "config" from "fs->f",
595     * using a cast.  However, "config" is used so often that a
596     * cast each time would be very ugly, and the extra indirection
597     * would waste CPU cycles.  Therefore we store "config" in
598     * "csp->config", and "fs" in "csp->config->config_file_list".
599     */
600    config->config_file_list = fs;
601
602    /*
603     * Set to defaults
604     */
605    config->multi_threaded    = 1;
606    config->hport             = HADDR_PORT;
607    config->buffer_limit      = 4096 * 1024;
608    config->usermanual        = strdup(USER_MANUAL_URL);
609    config->proxy_args        = strdup("");
610
611    if ((configfp = fopen(configfile, "r")) == NULL)
612    {
613       log_error(LOG_LEVEL_FATAL, "can't open configuration file '%s':  %E",
614               configfile);
615       /* Never get here - LOG_LEVEL_FATAL causes program exit */
616    }
617
618    while (read_config_line(buf, sizeof(buf), configfp, &linenum) != NULL)
619    {
620       char cmd[BUFFER_SIZE];
621       char arg[BUFFER_SIZE];
622       char tmp[BUFFER_SIZE];
623 #ifdef FEATURE_ACL
624       struct access_control_list *cur_acl;
625 #endif /* def FEATURE_ACL */
626       struct forward_spec *cur_fwd;
627       int vec_count;
628       char *vec[3];
629
630       strcpy(tmp, buf);
631
632       /* Copy command (i.e. up to space or tab) into cmd */
633       p = buf;
634       q = cmd;
635       while (*p && (*p != ' ') && (*p != '\t'))
636       {
637          *q++ = *p++;
638       }
639       *q = '\0';
640
641       /* Skip over the whitespace in buf */
642       while (*p && ((*p == ' ') || (*p == '\t')))
643       {
644          p++;
645       }
646
647       /* Copy the argument into arg */
648       strcpy(arg, p);
649
650       /* Should never happen, but check this anyway */
651       if (*cmd == '\0')
652       {
653          continue;
654       }
655
656       /* Make sure the command field is lower case */
657       for (p=cmd; *p; p++)
658       {
659          if (ijb_isupper(*p))
660          {
661             *p = ijb_tolower(*p);
662          }
663       }
664
665       /* Save the argument for show-proxy-args */
666       savearg(cmd, arg, config);
667
668
669       switch( hash_string( cmd ) )
670       {
671 /* *************************************************************************
672  * actionsfile actions-file-name
673  * In confdir by default
674  * *************************************************************************/
675          case hash_actions_file :
676             i = 0;
677             while ((i < MAX_ACTION_FILES) && (NULL != config->actions_file[i]))
678             {
679                i++;
680             }
681
682             if (i >= MAX_ACTION_FILES)
683             {
684                log_error(LOG_LEVEL_FATAL, "Too many 'actionsfile' directives in config file - limit is %d.\n"
685                   "(You can increase this limit by changing MAX_ACTION_FILES in project.h and recompiling).",
686                   MAX_ACTION_FILES);
687             }
688             config->actions_file_short[i] = strdup(arg);
689             p = malloc(strlen(arg) + sizeof(".action"));
690             if (p == NULL)
691             {
692                log_error(LOG_LEVEL_FATAL, "Out of memory");
693             }
694             strcpy(p, arg);
695             strcat(p, ".action");
696             config->actions_file[i] = make_path(config->confdir, p);
697             free(p);
698             continue;
699
700 /* *************************************************************************
701  * admin-address email-address
702  * *************************************************************************/
703          case hash_admin_address :
704             freez(config->admin_address);
705             config->admin_address = strdup(arg);
706             continue;
707
708 /* *************************************************************************
709  * buffer-limit n
710  * *************************************************************************/
711          case hash_buffer_limit :
712             config->buffer_limit = (size_t) 1024 * atoi(arg);
713             continue;
714
715 /* *************************************************************************
716  * confdir directory-name
717  * *************************************************************************/
718          case hash_confdir :
719             freez(config->confdir);
720             config->confdir = make_path( NULL, arg);
721             continue;
722
723 /* *************************************************************************
724  * debug n
725  * Specifies debug level, multiple values are ORed together.
726  * *************************************************************************/
727          case hash_debug :
728             config->debug |= atoi(arg);
729             continue;
730
731 /* *************************************************************************
732  * deny-access source-ip[/significant-bits] [dest-ip[/significant-bits]]
733  * *************************************************************************/
734 #ifdef FEATURE_ACL
735          case hash_deny_access:
736             vec_count = ssplit(arg, " \t", vec, SZ(vec), 1, 1);
737
738             if ((vec_count != 1) && (vec_count != 2))
739             {
740                log_error(LOG_LEVEL_ERROR, "Wrong number of parameters for "
741                      "deny-access directive in configuration file.");
742                string_append(&config->proxy_args,
743                   "<br>\nWARNING: Wrong number of parameters for "
744                   "deny-access directive in configuration file.<br><br>\n");
745                continue;
746             }
747
748             /* allocate a new node */
749             cur_acl = (struct access_control_list *) zalloc(sizeof(*cur_acl));
750
751             if (cur_acl == NULL)
752             {
753                log_error(LOG_LEVEL_FATAL, "can't allocate memory for configuration");
754                /* Never get here - LOG_LEVEL_FATAL causes program exit */
755                continue;
756             }
757             cur_acl->action = ACL_DENY;
758
759             if (acl_addr(vec[0], cur_acl->src) < 0)
760             {
761                log_error(LOG_LEVEL_ERROR, "Invalid source IP for deny-access "
762                      "directive in configuration file: \"%s\"", vec[0]);
763                string_append(&config->proxy_args,
764                   "<br>\nWARNING: Invalid source IP for deny-access directive"
765                   " in configuration file: \"");
766                string_append(&config->proxy_args,
767                   vec[0]);
768                string_append(&config->proxy_args,
769                   "\"<br><br>\n");
770                freez(cur_acl);
771                continue;
772             }
773             if (vec_count == 2)
774             {
775                if (acl_addr(vec[1], cur_acl->dst) < 0)
776                {
777                   log_error(LOG_LEVEL_ERROR, "Invalid destination IP for deny-access "
778                         "directive in configuration file: \"%s\"", vec[0]);
779                   string_append(&config->proxy_args,
780                      "<br>\nWARNING: Invalid destination IP for deny-access directive"
781                      " in configuration file: \"");
782                   string_append(&config->proxy_args,
783                      vec[0]);
784                   string_append(&config->proxy_args,
785                      "\"<br><br>\n");
786                   freez(cur_acl);
787                   continue;
788                }
789             }
790
791             /*
792              * Add it to the list.  Note we reverse the list to get the
793              * behaviour the user expects.  With both the ACL and
794              * actions file, the last match wins.  However, the internal
795              * implementations are different:  The actions file is stored
796              * in the same order as the file, and scanned completely.
797              * With the ACL, we reverse the order as we load it, then
798              * when we scan it we stop as soon as we get a match.
799              */
800             cur_acl->next  = config->acl;
801             config->acl = cur_acl;
802
803             continue;
804 #endif /* def FEATURE_ACL */
805
806 /* *************************************************************************
807  * enable-edit-actions 0|1
808  * *************************************************************************/
809 #ifdef FEATURE_CGI_EDIT_ACTIONS
810          case hash_enable_edit_actions:
811             if ((*arg != '\0') && (0 != atoi(arg)))
812             {
813                config->feature_flags |= RUNTIME_FEATURE_CGI_EDIT_ACTIONS;
814             }
815             else
816             {
817                config->feature_flags &= ~RUNTIME_FEATURE_CGI_EDIT_ACTIONS;
818             }
819             continue;
820 #endif /* def FEATURE_CGI_EDIT_ACTIONS */
821
822 /* *************************************************************************
823  * enable-remote-toggle 0|1
824  * *************************************************************************/
825 #ifdef FEATURE_CGI_EDIT_ACTIONS
826          case hash_enable_remote_toggle:
827             if ((*arg != '\0') && (0 != atoi(arg)))
828             {
829                config->feature_flags |= RUNTIME_FEATURE_CGI_TOGGLE;
830             }
831             else
832             {
833                config->feature_flags &= ~RUNTIME_FEATURE_CGI_TOGGLE;
834             }
835             continue;
836 #endif /* def FEATURE_CGI_EDIT_ACTIONS */
837
838 /* *************************************************************************
839  * forward url-pattern (.|http-proxy-host[:port])
840  * *************************************************************************/
841          case hash_forward:
842             vec_count = ssplit(arg, " \t", vec, SZ(vec), 1, 1);
843
844             if (vec_count != 2)
845             {
846                log_error(LOG_LEVEL_ERROR, "Wrong number of parameters for forward "
847                      "directive in configuration file.");
848                string_append(&config->proxy_args,
849                   "<br>\nWARNING: Wrong number of parameters for "
850                   "forward directive in configuration file.");
851                continue;
852             }
853
854             /* allocate a new node */
855             cur_fwd = zalloc(sizeof(*cur_fwd));
856             if (cur_fwd == NULL)
857             {
858                log_error(LOG_LEVEL_FATAL, "can't allocate memory for configuration");
859                /* Never get here - LOG_LEVEL_FATAL causes program exit */
860                continue;
861             }
862
863             cur_fwd->type = SOCKS_NONE;
864
865             /* Save the URL pattern */
866             if (create_url_spec(cur_fwd->url, vec[0]))
867             {
868                log_error(LOG_LEVEL_ERROR, "Bad URL specifier for forward "
869                      "directive in configuration file.");
870                string_append(&config->proxy_args,
871                   "<br>\nWARNING: Bad URL specifier for "
872                   "forward directive in configuration file.");
873                continue;
874             }
875
876             /* Parse the parent HTTP proxy host:port */
877             p = vec[1];
878
879             if (strcmp(p, ".") != 0)
880             {
881                cur_fwd->forward_host = strdup(p);
882
883                if (NULL != (p = strchr(cur_fwd->forward_host, ':')))
884                {
885                   *p++ = '\0';
886                   cur_fwd->forward_port = atoi(p);
887                }
888
889                if (cur_fwd->forward_port <= 0)
890                {
891                   cur_fwd->forward_port = 8000;
892                }
893             }
894
895             /* Add to list. */
896             cur_fwd->next = config->forward;
897             config->forward = cur_fwd;
898
899             continue;
900
901 /* *************************************************************************
902  * forward-socks4 url-pattern socks-proxy[:port] (.|http-proxy[:port])
903  * *************************************************************************/
904          case hash_forward_socks4:
905             vec_count = ssplit(arg, " \t", vec, SZ(vec), 1, 1);
906
907             if (vec_count != 3)
908             {
909                log_error(LOG_LEVEL_ERROR, "Wrong number of parameters for "
910                      "forward-socks4 directive in configuration file.");
911                string_append(&config->proxy_args,
912                   "<br>\nWARNING: Wrong number of parameters for "
913                   "forward-socks4 directive in configuration file.");
914                continue;
915             }
916
917             /* allocate a new node */
918             cur_fwd = zalloc(sizeof(*cur_fwd));
919             if (cur_fwd == NULL)
920             {
921                log_error(LOG_LEVEL_FATAL, "can't allocate memory for configuration");
922                /* Never get here - LOG_LEVEL_FATAL causes program exit */
923                continue;
924             }
925
926             cur_fwd->type = SOCKS_4;
927
928             /* Save the URL pattern */
929             if (create_url_spec(cur_fwd->url, vec[0]))
930             {
931                log_error(LOG_LEVEL_ERROR, "Bad URL specifier for forward-socks4 "
932                      "directive in configuration file.");
933                string_append(&config->proxy_args,
934                   "<br>\nWARNING: Bad URL specifier for "
935                   "forward-socks4 directive in configuration file.");
936                continue;
937             }
938
939             /* Parse the SOCKS proxy host[:port] */
940             p = vec[1];
941
942             if (strcmp(p, ".") != 0)
943             {
944                cur_fwd->gateway_host = strdup(p);
945
946                if (NULL != (p = strchr(cur_fwd->gateway_host, ':')))
947                {
948                   *p++ = '\0';
949                   cur_fwd->gateway_port = atoi(p);
950                }
951                if (cur_fwd->gateway_port <= 0)
952                {
953                   cur_fwd->gateway_port = 1080;
954                }
955             }
956
957             /* Parse the parent HTTP proxy host[:port] */
958             p = vec[2];
959
960             if (strcmp(p, ".") != 0)
961             {
962                cur_fwd->forward_host = strdup(p);
963
964                if (NULL != (p = strchr(cur_fwd->forward_host, ':')))
965                {
966                   *p++ = '\0';
967                   cur_fwd->forward_port = atoi(p);
968                }
969
970                if (cur_fwd->forward_port <= 0)
971                {
972                   cur_fwd->forward_port = 8000;
973                }
974             }
975
976             /* Add to list. */
977             cur_fwd->next = config->forward;
978             config->forward = cur_fwd;
979
980             continue;
981
982 /* *************************************************************************
983  * forward-socks4a url-pattern socks-proxy[:port] (.|http-proxy[:port])
984  * *************************************************************************/
985          case hash_forward_socks4a:
986             vec_count = ssplit(arg, " \t", vec, SZ(vec), 1, 1);
987
988             if (vec_count != 3)
989             {
990                log_error(LOG_LEVEL_ERROR, "Wrong number of parameters for "
991                      "forward-socks4a directive in configuration file.");
992                string_append(&config->proxy_args,
993                   "<br>\nWARNING: Wrong number of parameters for "
994                   "forward-socks4a directive in configuration file.");
995                continue;
996             }
997
998             /* allocate a new node */
999             cur_fwd = zalloc(sizeof(*cur_fwd));
1000             if (cur_fwd == NULL)
1001             {
1002                log_error(LOG_LEVEL_FATAL, "can't allocate memory for configuration");
1003                /* Never get here - LOG_LEVEL_FATAL causes program exit */
1004                continue;
1005             }
1006
1007             cur_fwd->type = SOCKS_4A;
1008
1009             /* Save the URL pattern */
1010             if (create_url_spec(cur_fwd->url, vec[0]))
1011             {
1012                log_error(LOG_LEVEL_ERROR, "Bad URL specifier for forward-socks4a "
1013                      "directive in configuration file.");
1014                string_append(&config->proxy_args,
1015                   "<br>\nWARNING: Bad URL specifier for "
1016                   "forward-socks4a directive in configuration file.");
1017                continue;
1018             }
1019
1020             /* Parse the SOCKS proxy host[:port] */
1021             p = vec[1];
1022
1023             cur_fwd->gateway_host = strdup(p);
1024
1025             if (NULL != (p = strchr(cur_fwd->gateway_host, ':')))
1026             {
1027                *p++ = '\0';
1028                cur_fwd->gateway_port = atoi(p);
1029             }
1030             if (cur_fwd->gateway_port <= 0)
1031             {
1032                cur_fwd->gateway_port = 1080;
1033             }
1034
1035             /* Parse the parent HTTP proxy host[:port] */
1036             p = vec[2];
1037
1038             if (strcmp(p, ".") != 0)
1039             {
1040                cur_fwd->forward_host = strdup(p);
1041
1042                if (NULL != (p = strchr(cur_fwd->forward_host, ':')))
1043                {
1044                   *p++ = '\0';
1045                   cur_fwd->forward_port = atoi(p);
1046                }
1047
1048                if (cur_fwd->forward_port <= 0)
1049                {
1050                   cur_fwd->forward_port = 8000;
1051                }
1052             }
1053
1054             /* Add to list. */
1055             cur_fwd->next = config->forward;
1056             config->forward = cur_fwd;
1057
1058             continue;
1059
1060 /* *************************************************************************
1061  * jarfile jar-file-name
1062  * In logdir by default
1063  * *************************************************************************/
1064 #ifdef FEATURE_COOKIE_JAR
1065          case hash_jarfile :
1066             freez(config->jarfile);
1067             config->jarfile = make_path(config->logdir, arg);
1068             continue;
1069 #endif /* def FEATURE_COOKIE_JAR */
1070
1071 /* *************************************************************************
1072  * listen-address [ip][:port]
1073  * *************************************************************************/
1074          case hash_listen_address :
1075             freez(config->haddr);
1076             config->haddr = strdup(arg);
1077             continue;
1078
1079 /* *************************************************************************
1080  * logdir directory-name
1081  * *************************************************************************/
1082          case hash_logdir :
1083             freez(config->logdir);
1084             config->logdir = make_path(NULL, arg);
1085             continue;
1086
1087 /* *************************************************************************
1088  * logfile log-file-name
1089  * In logdir by default
1090  * *************************************************************************/
1091          case hash_logfile :
1092             freez(config->logfile);
1093             config->logfile = no_daemon ? NULL : make_path(config->logdir, arg);
1094             continue;
1095
1096 /* *************************************************************************
1097  * permit-access source-ip[/significant-bits] [dest-ip[/significant-bits]]
1098  * *************************************************************************/
1099 #ifdef FEATURE_ACL
1100          case hash_permit_access:
1101             vec_count = ssplit(arg, " \t", vec, SZ(vec), 1, 1);
1102
1103             if ((vec_count != 1) && (vec_count != 2))
1104             {
1105                log_error(LOG_LEVEL_ERROR, "Wrong number of parameters for "
1106                      "permit-access directive in configuration file.");
1107                string_append(&config->proxy_args,
1108                   "<br>\nWARNING: Wrong number of parameters for "
1109                   "permit-access directive in configuration file.<br><br>\n");
1110
1111                continue;
1112             }
1113
1114             /* allocate a new node */
1115             cur_acl = (struct access_control_list *) zalloc(sizeof(*cur_acl));
1116
1117             if (cur_acl == NULL)
1118             {
1119                log_error(LOG_LEVEL_FATAL, "can't allocate memory for configuration");
1120                /* Never get here - LOG_LEVEL_FATAL causes program exit */
1121                continue;
1122             }
1123             cur_acl->action = ACL_PERMIT;
1124
1125             if (acl_addr(vec[0], cur_acl->src) < 0)
1126             {
1127                log_error(LOG_LEVEL_ERROR, "Invalid source IP for permit-access "
1128                      "directive in configuration file: \"%s\"", vec[0]);
1129                string_append(&config->proxy_args,
1130                   "<br>\nWARNING: Invalid source IP for permit-access directive"
1131                   " in configuration file: \"");
1132                string_append(&config->proxy_args,
1133                   vec[0]);
1134                string_append(&config->proxy_args,
1135                   "\"<br><br>\n");
1136                freez(cur_acl);
1137                continue;
1138             }
1139             if (vec_count == 2)
1140             {
1141                if (acl_addr(vec[1], cur_acl->dst) < 0)
1142                {
1143                   log_error(LOG_LEVEL_ERROR, "Invalid destination IP for "
1144                         "permit-access directive in configuration file: \"%s\"",
1145                         vec[0]);
1146                   string_append(&config->proxy_args,
1147                      "<br>\nWARNING: Invalid destination IP for permit-access directive"
1148                      " in configuration file: \"");
1149                   string_append(&config->proxy_args,
1150                      vec[0]);
1151                   string_append(&config->proxy_args,
1152                      "\"<br><br>\n");
1153                   freez(cur_acl);
1154                   continue;
1155                }
1156             }
1157
1158             /*
1159              * Add it to the list.  Note we reverse the list to get the
1160              * behaviour the user expects.  With both the ACL and
1161              * actions file, the last match wins.  However, the internal
1162              * implementations are different:  The actions file is stored
1163              * in the same order as the file, and scanned completely.
1164              * With the ACL, we reverse the order as we load it, then
1165              * when we scan it we stop as soon as we get a match.
1166              */
1167             cur_acl->next  = config->acl;
1168             config->acl = cur_acl;
1169
1170             continue;
1171 #endif /* def FEATURE_ACL */
1172
1173 /* *************************************************************************
1174  * proxy-info-url url
1175  * *************************************************************************/
1176          case hash_proxy_info_url :
1177             freez(config->proxy_info_url);
1178             config->proxy_info_url = strdup(arg);
1179             continue;
1180
1181 /* *************************************************************************
1182  * re_filterfile file-name
1183  * In confdir by default.
1184  * *************************************************************************/
1185          case hash_filterfile :
1186             freez(config->re_filterfile);
1187             config->re_filterfile = make_path(config->confdir, arg);
1188             continue;
1189
1190 /* *************************************************************************
1191  * single-threaded
1192  * *************************************************************************/
1193          case hash_single_threaded :
1194             config->multi_threaded = 0;
1195             continue;
1196
1197 /* *************************************************************************
1198  * toggle (0|1)
1199  * *************************************************************************/
1200 #ifdef FEATURE_TOGGLE
1201          case hash_toggle :
1202             g_bToggleIJB = atoi(arg);
1203             continue;
1204 #endif /* def FEATURE_TOGGLE */
1205
1206 /* *************************************************************************
1207  * trust-info-url url
1208  * *************************************************************************/
1209 #ifdef FEATURE_TRUST
1210          case hash_trust_info_url :
1211             enlist(config->trust_info, arg);
1212             continue;
1213 #endif /* def FEATURE_TRUST */
1214
1215 /* *************************************************************************
1216  * trustfile filename
1217  * (In confdir by default.)
1218  * *************************************************************************/
1219 #ifdef FEATURE_TRUST
1220          case hash_trustfile :
1221             freez(config->trustfile);
1222             config->trustfile = make_path(config->confdir, arg);
1223             continue;
1224 #endif /* def FEATURE_TRUST */
1225
1226 /* *************************************************************************
1227  * usermanual url
1228  * *************************************************************************/
1229          case hash_usermanual :
1230             freez(config->usermanual);
1231             config->usermanual = strdup(arg);
1232             continue;
1233
1234 /* *************************************************************************
1235  * Win32 Console options:
1236  * *************************************************************************/
1237
1238 /* *************************************************************************
1239  * hide-console
1240  * *************************************************************************/
1241 #ifdef _WIN_CONSOLE
1242          case hash_hide_console :
1243             hideConsole = 1;
1244             continue;
1245 #endif /*def _WIN_CONSOLE*/
1246
1247
1248 /* *************************************************************************
1249  * Win32 GUI options:
1250  * *************************************************************************/
1251
1252 #if defined(_WIN32) && ! defined(_WIN_CONSOLE)
1253 /* *************************************************************************
1254  * activity-animation (0|1)
1255  * *************************************************************************/
1256          case hash_activity_animation :
1257             g_bShowActivityAnimation = atoi(arg);
1258             continue;
1259
1260 /* *************************************************************************
1261  *  close-button-minimizes (0|1)
1262  * *************************************************************************/
1263          case hash_close_button_minimizes :
1264             g_bCloseHidesWindow = atoi(arg);
1265             continue;
1266
1267 /* *************************************************************************
1268  * log-buffer-size (0|1)
1269  * *************************************************************************/
1270          case hash_log_buffer_size :
1271             g_bLimitBufferSize = atoi(arg);
1272             continue;
1273
1274 /* *************************************************************************
1275  * log-font-name fontnane
1276  * *************************************************************************/
1277          case hash_log_font_name :
1278             strcpy( g_szFontFaceName, arg );
1279             continue;
1280
1281 /* *************************************************************************
1282  * log-font-size n
1283  * *************************************************************************/
1284          case hash_log_font_size :
1285             g_nFontSize = atoi(arg);
1286             continue;
1287
1288 /* *************************************************************************
1289  * log-highlight-messages (0|1)
1290  * *************************************************************************/
1291          case hash_log_highlight_messages :
1292             g_bHighlightMessages = atoi(arg);
1293             continue;
1294
1295 /* *************************************************************************
1296  * log-max-lines n
1297  * *************************************************************************/
1298          case hash_log_max_lines :
1299             g_nMaxBufferLines = atoi(arg);
1300             continue;
1301
1302 /* *************************************************************************
1303  * log-messages (0|1)
1304  * *************************************************************************/
1305          case hash_log_messages :
1306             g_bLogMessages = atoi(arg);
1307             continue;
1308
1309 /* *************************************************************************
1310  * show-on-task-bar (0|1)
1311  * *************************************************************************/
1312          case hash_show_on_task_bar :
1313             g_bShowOnTaskBar = atoi(arg);
1314             continue;
1315
1316 #endif /* defined(_WIN32) && ! defined(_WIN_CONSOLE) */
1317
1318
1319 /* *************************************************************************
1320  * Warnings about unsupported features
1321  * *************************************************************************/
1322 #ifndef FEATURE_ACL
1323          case hash_deny_access:
1324 #endif /* ndef FEATURE_ACL */
1325 #ifndef FEATURE_CGI_EDIT_ACTIONS
1326          case hash_enable_edit_actions:
1327          case hash_enable_remote_toggle:
1328 #endif /* def FEATURE_CGI_EDIT_ACTIONS */
1329 #ifndef FEATURE_COOKIE_JAR
1330          case hash_jarfile :
1331 #endif /* ndef FEATURE_COOKIE_JAR */
1332 #ifndef FEATURE_ACL
1333          case hash_permit_access:
1334 #endif /* ndef FEATURE_ACL */
1335 #ifndef FEATURE_TOGGLE
1336          case hash_toggle :
1337 #endif /* ndef FEATURE_TOGGLE */
1338 #ifndef FEATURE_TRUST
1339          case hash_trustfile :
1340          case hash_trust_info_url :
1341 #endif /* ndef FEATURE_TRUST */
1342
1343 #ifndef _WIN_CONSOLE
1344          case hash_hide_console :
1345 #endif /* ndef _WIN_CONSOLE */
1346
1347 #if defined(_WIN_CONSOLE) || ! defined(_WIN32)
1348          case hash_activity_animation :
1349          case hash_close_button_minimizes :
1350          case hash_log_buffer_size :
1351          case hash_log_font_name :
1352          case hash_log_font_size :
1353          case hash_log_highlight_messages :
1354          case hash_log_max_lines :
1355          case hash_log_messages :
1356          case hash_show_on_task_bar :
1357 #endif /* defined(_WIN_CONSOLE) || ! defined(_WIN32) */
1358             /* These warnings are annoying - so hide them. -- Jon */
1359             /* log_error(LOG_LEVEL_INFO, "Unsupported directive \"%s\" ignored.", cmd); */
1360             continue;
1361
1362 /* *************************************************************************/
1363          default :
1364 /* *************************************************************************/
1365             /*
1366              * I decided that I liked this better as a warning than an
1367              * error.  To change back to an error, just change log level
1368              * to LOG_LEVEL_FATAL.
1369              */
1370             log_error(LOG_LEVEL_ERROR, "Unrecognized directive '%s' (%luul) in line %lu in "
1371                   "configuration file (%s).",  buf, hash_string(cmd), linenum, configfile);
1372             string_append(&config->proxy_args, "<br>\nWARNING: unrecognized directive : ");
1373             string_append(&config->proxy_args, buf);
1374             string_append(&config->proxy_args, "<br><br>\n");
1375             continue;
1376
1377 /* *************************************************************************/
1378       } /* end switch( hash_string(cmd) ) */
1379    } /* end while ( read_config_line(...) ) */
1380
1381    fclose(configfp);
1382
1383    if (NULL == config->proxy_args)
1384    {
1385       log_error(LOG_LEVEL_FATAL, "Out of memory loading config - insufficient memory for config->proxy_args");
1386    }
1387
1388    init_error_log(Argv[0], config->logfile, config->debug);
1389
1390    if (config->actions_file[0])
1391    {
1392       add_loader(load_actions_file, config);
1393    }
1394
1395    if (config->re_filterfile)
1396    {
1397       add_loader(load_re_filterfile, config);
1398    }
1399
1400 #ifdef FEATURE_TRUST
1401    if (config->trustfile)
1402    {
1403       add_loader(load_trustfile, config);
1404    }
1405 #endif /* def FEATURE_TRUST */
1406
1407 #ifdef FEATURE_COOKIE_JAR
1408    if ( NULL != config->jarfile )
1409    {
1410       if ( NULL == (config->jar = fopen(config->jarfile, "a")) )
1411       {
1412          log_error(LOG_LEVEL_FATAL, "can't open jarfile '%s': %E", config->jarfile);
1413          /* Never get here - LOG_LEVEL_FATAL causes program exit */
1414       }
1415       setbuf(config->jar, NULL);
1416    }
1417 #endif /* def FEATURE_COOKIE_JAR */
1418
1419    if ( NULL == config->haddr )
1420    {
1421       config->haddr = strdup( HADDR_DEFAULT );
1422    }
1423
1424    if ( NULL != config->haddr )
1425    {
1426       if (NULL != (p = strchr(config->haddr, ':')))
1427       {
1428          *p++ = '\0';
1429          if (*p)
1430          {
1431             config->hport = atoi(p);
1432          }
1433       }
1434
1435       if (config->hport <= 0)
1436       {
1437          *--p = ':';
1438          log_error(LOG_LEVEL_FATAL, "invalid bind port spec %s", config->haddr);
1439          /* Never get here - LOG_LEVEL_FATAL causes program exit */
1440       }
1441       if (*config->haddr == '\0')
1442       {
1443          config->haddr = NULL;
1444       }
1445    }
1446
1447    /*
1448     * Want to run all the loaders once now.
1449     *
1450     * Need to set up a fake csp, so they can get to the config.
1451     */
1452    fake_csp = (struct client_state *) zalloc (sizeof(*fake_csp));
1453    fake_csp->config = config;
1454
1455    if (run_loader(fake_csp))
1456    {
1457       freez(fake_csp);
1458       log_error(LOG_LEVEL_FATAL, "A loader failed while loading config file. Exiting.");
1459       /* Never get here - LOG_LEVEL_FATAL causes program exit */
1460    }
1461    freez(fake_csp);
1462
1463 /* FIXME: this is a kludge for win32 */
1464 #if defined(_WIN32) && !defined (_WIN_CONSOLE)
1465
1466    g_default_actions_file  = config->actions_file[1]; /* FIXME Hope this is default.action */
1467    g_user_actions_file = config->actions_file[2]; /* FIXME Hope this is user.action */
1468    g_re_filterfile    = config->re_filterfile;
1469
1470 #ifdef FEATURE_TRUST
1471    g_trustfile        = config->trustfile;
1472 #endif /* def FEATURE_TRUST */
1473
1474
1475 #endif /* defined(_WIN32) && !defined (_WIN_CONSOLE) */
1476 /* FIXME: end kludge */
1477
1478
1479    config->need_bind = 1;
1480
1481    if (current_configfile)
1482    {
1483       struct configuration_spec * oldcfg = (struct configuration_spec *)
1484                                            current_configfile->f;
1485       /*
1486        * Check if config->haddr,hport == oldcfg->haddr,hport
1487        *
1488        * The following could be written more compactly as a single,
1489        * (unreadably long) if statement.
1490        */
1491       config->need_bind = 0;
1492       if (config->hport != oldcfg->hport)
1493       {
1494          config->need_bind = 1;
1495       }
1496       else if (config->haddr == NULL)
1497       {
1498          if (oldcfg->haddr != NULL)
1499          {
1500             config->need_bind = 1;
1501          }
1502       }
1503       else if (oldcfg->haddr == NULL)
1504       {
1505          config->need_bind = 1;
1506       }
1507       else if (0 != strcmp(config->haddr, oldcfg->haddr))
1508       {
1509          config->need_bind = 1;
1510       }
1511
1512       current_configfile->unloader = unload_configfile;
1513    }
1514
1515    fs->next = files->next;
1516    files->next = fs;
1517
1518    current_configfile = fs;
1519
1520    return (config);
1521 }
1522
1523
1524 /*********************************************************************
1525  *
1526  * Function    :  savearg
1527  *
1528  * Description :  Called from `load_config'.  It saves each non-empty
1529  *                and non-comment line from config into
1530  *                config->proxy_args.  This is used to create the
1531  *                show-proxy-args page.  On error, frees
1532  *                config->proxy_args and sets it to NULL
1533  *
1534  * Parameters  :
1535  *          1  :  command = config setting that was found
1536  *          2  :  argument = the setting's argument (if any)
1537  *          3  :  config = Configuration to save into.
1538  *
1539  * Returns     :  N/A
1540  *
1541  *********************************************************************/
1542 static void savearg(char *command, char *argument, struct configuration_spec * config)
1543 {
1544    char * buf;
1545    char * s;
1546
1547    assert(command);
1548    assert(*command);
1549    assert(argument);
1550
1551    /*
1552     * Add config option name embedded in
1553     * link to it's section in the user-manual
1554     */
1555    buf = strdup("<a href=\"");
1556    string_append(&buf, config->usermanual);
1557    string_append(&buf, CONFIG_HELP_PREFIX);
1558    string_join  (&buf, string_toupper(command));
1559    string_append(&buf, "\">");
1560    string_append(&buf, command);
1561    string_append(&buf, "</a> ");
1562
1563    if (NULL == buf)
1564    {
1565       freez(config->proxy_args);
1566       return;
1567    }
1568
1569    if ( (NULL != argument) && ('\0' != *argument) )
1570    {
1571       s = html_encode(argument);
1572       if (NULL == s)
1573       {
1574          freez(buf);
1575          freez(config->proxy_args);
1576          return;
1577       }
1578
1579       if (strncmpic(argument, "http://", 7) == 0)
1580       {
1581          string_append(&buf, "<a href=\"");
1582          string_append(&buf, s);
1583          string_append(&buf, "\">");
1584          string_join  (&buf, s);
1585          string_append(&buf, "</a>");
1586       }
1587       else
1588       {
1589          string_join  (&buf, s);
1590       }
1591    }
1592
1593    string_append(&buf, "<br>\n");
1594
1595    string_join(&config->proxy_args, buf);
1596 }
1597
1598
1599 /*
1600   Local Variables:
1601   tab-width: 3
1602   end:
1603 */