Incorporate Fabian Keil's patch work:\rhttp://www.fabiankeil.de/sourcecode/privoxy/
[privoxy.git] / jcc.c
1 const char jcc_rcs[] = "$Id: jcc.c,v 1.94 2006/07/18 14:48:46 david__schmidt Exp $";
2 /*********************************************************************
3  *
4  * File        :  $Source: /cvsroot/ijbswa/current/jcc.c,v $
5  *
6  * Purpose     :  Main file.  Contains main() method, main loop, and
7  *                the main connection-handling function.
8  *
9  * Copyright   :  Written by and Copyright (C) 2001 the SourceForge
10  *                Privoxy team. http://www.privoxy.org/
11  *
12  *                Based on the Internet Junkbuster originally written
13  *                by and Copyright (C) 1997 Anonymous Coders and
14  *                Junkbusters Corporation.  http://www.junkbusters.com
15  *
16  *                This program is free software; you can redistribute it
17  *                and/or modify it under the terms of the GNU General
18  *                Public License as published by the Free Software
19  *                Foundation; either version 2 of the License, or (at
20  *                your option) any later version.
21  *
22  *                This program is distributed in the hope that it will
23  *                be useful, but WITHOUT ANY WARRANTY; without even the
24  *                implied warranty of MERCHANTABILITY or FITNESS FOR A
25  *                PARTICULAR PURPOSE.  See the GNU General Public
26  *                License for more details.
27  *
28  *                The GNU General Public License should be included with
29  *                this file.  If not, you can view it at
30  *                http://www.gnu.org/copyleft/gpl.html
31  *                or write to the Free Software Foundation, Inc., 59
32  *                Temple Place - Suite 330, Boston, MA  02111-1307, USA.
33  *
34  * Revisions   :
35  *    $Log: jcc.c,v $
36  *    Revision 1.94  2006/07/18 14:48:46  david__schmidt
37  *    Reorganizing the repository: swapping out what was HEAD (the old 3.1 branch)
38  *    with what was really the latest development (the v_3_0_branch branch)
39  *
40  *    Revision 1.92.2.16  2005/04/03 20:10:50  david__schmidt
41  *    Thanks to Jindrich Makovicka for a race condition fix for the log
42  *    file.  The race condition remains for non-pthread implementations.
43  *    Reference patch #1175720.
44  *
45  *    Revision 1.92.2.15  2004/10/03 12:53:32  david__schmidt
46  *    Add the ability to check jpeg images for invalid
47  *    lengths of comment blocks.  Defensive strategy
48  *    against the exploit:
49  *       Microsoft Security Bulletin MS04-028
50  *       Buffer Overrun in JPEG Processing (GDI+) Could
51  *       Allow Code Execution (833987)
52  *    Enabled with +inspect-jpegs in actions files.
53  *
54  *    Revision 1.92.2.14  2003/12/12 12:52:53  oes
55  *    - Fixed usage info for non-unix platforms
56  *    - Fixed small cmdline parsing bug
57  *
58  *    Revision 1.92.2.13  2003/11/27 19:20:27  oes
59  *    Diagnostics: Now preserve the returncode of pthread_create
60  *    in errno. Closes BR #775721. Thanks to Geoffrey Hausheer.
61  *
62  *    Revision 1.92.2.12  2003/07/11 11:34:19  oes
63  *    No longer ignore SIGCHLD. Fixes bug #769381
64  *
65  *    Revision 1.92.2.11  2003/05/14 12:32:02  oes
66  *    Close jarfile on graceful exit, remove stray line
67  *
68  *    Revision 1.92.2.10  2003/05/08 15:13:46  oes
69  *    Cosmetics: Killed a warning, a typo and an allocation left at exit
70  *
71  *    Revision 1.92.2.9  2003/04/03 15:08:42  oes
72  *    No longer rely on non-POSIX.1 extensions of getcwd().
73  *    Fixes bug #711001
74  *
75  *    Revision 1.92.2.8  2003/03/31 13:12:32  oes
76  *    Replaced setenv() by posix-compliant putenv()
77  *    Thanks to Neil McCalden (nmcc AT users.sf.net).
78  *
79  *    Revision 1.92.2.7  2003/03/17 16:48:59  oes
80  *    Added chroot ability, thanks to patch by Sviatoslav Sviridov
81  *
82  *    Revision 1.92.2.6  2003/03/11 11:55:00  oes
83  *    Clean-up and extension of improvements for forked mode:
84  *     - Child's return code now consists of flags RC_FLAG_*
85  *     - Reporting toggle to parent now properly #ifdef'ed
86  *     - Children now report blocking to parent. This enables
87  *       statistics in forked mode
88  *
89  *    Revision 1.92.2.5  2003/03/10 23:45:32  oes
90  *    Fixed bug #700381: Non-Threaded version now capable of being toggled.
91  *    Children now report having been toggled through _exit(17), parents
92  *    watch for that code and toggle themselves if found.
93  *
94  *    Revision 1.92.2.4  2003/03/07 03:41:04  david__schmidt
95  *    Wrapping all *_r functions (the non-_r versions of them) with 
96  *    mutex semaphores for OSX.  Hopefully this will take care of all 
97  *    of those pesky crash reports.
98  *
99  *    Revision 1.92.2.3  2003/02/28 12:53:06  oes
100  *    Fixed two mostly harmless mem leaks
101  *
102  *    Revision 1.92.2.2  2002/11/20 14:37:47  oes
103  *    Fix: Head of global clients list now initialized to NULL
104  *
105  *    Revision 1.92.2.1  2002/09/25 14:52:24  oes
106  *    Added basic support for OPTIONS and TRACE HTTP methods:
107  *     - New interceptor direct_response() added in chat().
108  *     - sed() moved to earlier in the process, so that the
109  *       Host: header is evaluated before actions and forwarding
110  *       are decided on.
111  *
112  *    Revision 1.92  2002/05/08 16:00:46  oes
113  *    Chat's buffer handling:
114  *     - Fixed bug with unchecked out-of-mem conditions
115  *       while reading client request & server headers
116  *     - No longer predict if the buffer limit will be exceeded
117  *       in the next read -- check add_to_iob's new
118  *       return code. If buffer couldn't be extended
119  *       (policy or out-of-mem) while
120  *       - reading from client: abort
121  *       - reading server headers: send error page
122  *       - buffering server body for filter: flush,
123  *         and if that fails: send error page
124  *
125  *    Revision 1.91  2002/04/08 20:35:58  swa
126  *    fixed JB spelling
127  *
128  *    Revision 1.90  2002/04/02 14:57:28  oes
129  *    Made sending wafers independent of FEATURE_COOKIE_JAR
130  *
131  *    Revision 1.89  2002/03/31 17:18:59  jongfoster
132  *    Win32 only: Enabling STRICT to fix a VC++ compile warning.
133  *
134  *    Revision 1.88  2002/03/27 14:32:43  david__schmidt
135  *    More compiler warning message maintenance
136  *
137  *    Revision 1.87  2002/03/26 22:29:54  swa
138  *    we have a new homepage!
139  *
140  *    Revision 1.86  2002/03/25 17:04:55  david__schmidt
141  *    Workaround for closing the jarfile before load_config() comes around again
142  *
143  *    Revision 1.85  2002/03/24 15:23:33  jongfoster
144  *    Name changes
145  *
146  *    Revision 1.84  2002/03/24 13:25:43  swa
147  *    name change related issues
148  *
149  *    Revision 1.83  2002/03/16 23:54:06  jongfoster
150  *    Adding graceful termination feature, to help look for memory leaks.
151  *    If you enable this (which, by design, has to be done by hand
152  *    editing config.h) and then go to http://i.j.b/die, then the program
153  *    will exit cleanly after the *next* request.  It should free all the
154  *    memory that was used.
155  *
156  *    Revision 1.82  2002/03/13 00:27:05  jongfoster
157  *    Killing warnings
158  *
159  *    Revision 1.81  2002/03/12 01:42:50  oes
160  *    Introduced modular filters
161  *
162  *    Revision 1.80  2002/03/11 22:07:05  david__schmidt
163  *    OS/2 port maintenance:
164  *    - Fixed EMX build - it had decayed a little
165  *    - Fixed inexplicable crash during FD_ZERO - must be due to a bad macro.
166  *      substituted a memset for now.
167  *
168  *    Revision 1.79  2002/03/09 20:03:52  jongfoster
169  *    - Making various functions return int rather than size_t.
170  *      (Undoing a recent change).  Since size_t is unsigned on
171  *      Windows, functions like read_socket that return -1 on
172  *      error cannot return a size_t.
173  *
174  *      THIS WAS A MAJOR BUG - it caused frequent, unpredictable
175  *      crashes, and also frequently caused JB to jump to 100%
176  *      CPU and stay there.  (Because it thought it had just
177  *      read ((unsigned)-1) == 4Gb of data...)
178  *
179  *    - The signature of write_socket has changed, it now simply
180  *      returns success=0/failure=nonzero.
181  *
182  *    - Trying to get rid of a few warnings --with-debug on
183  *      Windows, I've introduced a new type "jb_socket".  This is
184  *      used for the socket file descriptors.  On Windows, this
185  *      is SOCKET (a typedef for unsigned).  Everywhere else, it's
186  *      an int.  The error value can't be -1 any more, so it's
187  *      now JB_INVALID_SOCKET (which is -1 on UNIX, and in
188  *      Windows it maps to the #define INVALID_SOCKET.)
189  *
190  *    - The signature of bind_port has changed.
191  *
192  *    Revision 1.78  2002/03/08 21:35:04  oes
193  *    Added optional group supplement to --user option. Will now use default group of user if no group given
194  *
195  *    Revision 1.77  2002/03/07 03:52:06  oes
196  *     - Fixed compiler warnings etc
197  *     - Improved handling of failed DNS lookups
198  *
199  *    Revision 1.76  2002/03/06 22:54:35  jongfoster
200  *    Automated function-comment nitpicking.
201  *
202  *    Revision 1.75  2002/03/06 10:02:19  oes
203  *    Fixed stupid bug when --user was not given
204  *
205  *    Revision 1.74  2002/03/06 00:49:31  jongfoster
206  *    Fixing warning on Windows
207  *    Making #ifdefs that refer to the same variable consistently
208  *    use #ifdef unix rather than mixing #ifdef unix & #ifndef OS2
209  *
210  *    Revision 1.73  2002/03/05 23:57:30  hal9
211  *    Stray character 's' on line 1618 was breaking build.
212  *
213  *    Revision 1.72  2002/03/05 21:33:45  david__schmidt
214  *    - Re-enable OS/2 building after new parms were added
215  *    - Fix false out of memory report when resolving CGI templates when no IP
216  *      address is available of failed attempt (a la no such domain)
217  *
218  *    Revision 1.71  2002/03/05 18:13:56  oes
219  *    Added --user option
220  *
221  *    Revision 1.70  2002/03/05 04:52:42  oes
222  *    Deleted non-errlog debugging code
223  *
224  *    Revision 1.69  2002/03/04 23:50:00  jongfoster
225  *    Splitting off bind_port() call into bind_port_helper(), with
226  *    improved logging.
227  *
228  *    Revision 1.68  2002/03/04 20:17:32  oes
229  *    Fixed usage info
230  *
231  *    Revision 1.67  2002/03/04 18:18:57  oes
232  *    - Removed _DEBUG mode
233  *    - Cleand up cmdline parsing
234  *    - Introduced --no-daemon, --pidfile options
235  *    - Cleaned up signal handling:
236  *      - Terminate cleanly on INT, TERM and ABRT
237  *      - Schedule logfile for re-opening on HUP
238  *      - Ignore CHLD and PIPE
239  *      - Leave the rest with their default handlers
240  *      - Uniform handler registration
241  *    - Added usage() function
242  *    - Played styleguide police
243  *
244  *    Revision 1.66  2002/03/03 15:06:55  oes
245  *    Re-enabled automatic config reloading
246  *
247  *    Revision 1.65  2002/03/03 14:49:11  oes
248  *    Fixed CLF logging: Now uses client's original HTTP request
249  *
250  *    Revision 1.64  2002/03/03 09:18:03  joergs
251  *    Made jumbjuster work on AmigaOS again.
252  *
253  *    Revision 1.63  2002/03/02 04:14:50  david__schmidt
254  *    Clean up a little CRLF unpleasantness that suddenly appeared
255  *
256  *    Revision 1.62  2002/02/20 23:17:23  jongfoster
257  *    Detecting some out-of memory conditions and exiting with a log message.
258  *
259  *    Revision 1.61  2002/01/17 21:01:52  jongfoster
260  *    Moving all our URL and URL pattern parsing code to urlmatch.c.
261  *
262  *    Revision 1.60  2001/12/30 14:07:32  steudten
263  *    - Add signal handling (unix)
264  *    - Add SIGHUP handler (unix)
265  *    - Add creation of pidfile (unix)
266  *    - Add action 'top' in rc file (RH)
267  *    - Add entry 'SIGNALS' to manpage
268  *    - Add exit message to logfile (unix)
269  *
270  *    Revision 1.59  2001/12/13 14:07:18  oes
271  *    Fixed Bug: 503 error page now sent OK
272  *
273  *    Revision 1.58  2001/11/30 23:37:24  jongfoster
274  *    Renaming the Win32 config file to config.txt - this is almost the
275  *    same as the corresponding UNIX name "config"
276  *
277  *    Revision 1.57  2001/11/16 00:47:43  jongfoster
278  *    Changing the tty-disconnection code to use setsid().
279  *
280  *    Revision 1.56  2001/11/13 20:20:54  jongfoster
281  *    Tabs->spaces, fixing a bug with missing {} around an if()
282  *
283  *    Revision 1.55  2001/11/13 20:14:53  jongfoster
284  *    Patch for FreeBSD setpgrp() as suggested by Alexander Lazic
285  *
286  *    Revision 1.54  2001/11/07 00:03:14  steudten
287  *    Give reliable return value if an error
288  *    occurs not just 0 with new daemon mode.
289  *
290  *    Revision 1.53  2001/11/05 21:41:43  steudten
291  *    Add changes to be a real daemon just for unix os.
292  *    (change cwd to /, detach from controlling tty, set
293  *    process group and session leader to the own process.
294  *    Add DBG() Macro.
295  *    Add some fatal-error log message for failed malloc().
296  *    Add '-d' if compiled with 'configure --with-debug' to
297  *    enable debug output.
298  *
299  *    Revision 1.52  2001/10/26 20:11:20  jongfoster
300  *    Fixing type mismatch
301  *
302  *    Revision 1.51  2001/10/26 17:38:28  oes
303  *    Cosmetics
304  *
305  *    Revision 1.50  2001/10/25 03:40:48  david__schmidt
306  *    Change in porting tactics: OS/2's EMX porting layer doesn't allow multiple
307  *    threads to call select() simultaneously.  So, it's time to do a real, live,
308  *    native OS/2 port.  See defines for __EMX__ (the porting layer) vs. __OS2__
309  *    (native). Both versions will work, but using __OS2__ offers multi-threading.
310  *
311  *    Revision 1.49  2001/10/23 21:41:35  jongfoster
312  *    Added call to initialize the (statically-allocated of course)
313  *    "out of memory" CGI response.
314  *
315  *    Revision 1.48  2001/10/10 19:56:46  jongfoster
316  *    Moving some code that wasn't cookie-related out of an #ifdef
317  *    FEATURE_COOKIE_JAR
318  *
319  *    Revision 1.47  2001/10/10 16:44:36  oes
320  *    Added CONNECT destination port limitation check
321  *
322  *    Revision 1.46  2001/10/08 15:17:41  oes
323  *    Re-enabled SSL forwarding
324  *
325  *    Revision 1.45  2001/10/07 15:42:11  oes
326  *    Replaced 6 boolean members of csp with one bitmap (csp->flags)
327  *
328  *    Moved downgrading of the HTTP version from parse_http_request to
329  *      chat(), since we can't decide if it is necessary before we have
330  *      determined the actions for the URL. The HTTP command is now
331  *      *always* re-built so the repairs need no longer be special-cased.
332  *
333  *    filter_popups now gets a csp pointer so it can raise the new
334  *      CSP_FLAG_MODIFIED flag.
335  *
336  *    Bugfix
337  *
338  *    Added configurable size limit for the IOB. If the IOB grows so
339  *      large that the next read would exceed the limit, the header
340  *      is generated, and the header & unfiltered buffer are flushed
341  *      to the client. Chat then continues in non-buffering,
342  *      non-filtering body mode.
343  *
344  *    Revision 1.44  2001/10/02 18:13:57  oes
345  *    Ooops
346  *
347  *    Revision 1.43  2001/10/02 15:32:13  oes
348  *    Moved generation of hdr
349  *
350  *    Revision 1.42  2001/09/21 23:02:02  david__schmidt
351  *    Cleaning up 2 compiler warnings on OS/2.
352  *
353  *    Revision 1.41  2001/09/16 17:05:14  jongfoster
354  *    Removing unused #include showarg.h
355  *
356  *    Revision 1.40  2001/09/16 15:41:45  jongfoster
357  *    Fixing signed/unsigned comparison warning.
358  *
359  *    Revision 1.39  2001/09/16 13:21:27  jongfoster
360  *    Changes to use new list functions.
361  *
362  *    Revision 1.38  2001/09/16 13:01:46  jongfoster
363  *    Removing redundant function call that zeroed zalloc()'d memory.
364  *
365  *    Revision 1.37  2001/09/10 11:12:24  oes
366  *    Deleted unused variable
367  *
368  *    Revision 1.36  2001/09/10 10:56:15  oes
369  *    Silenced compiler warnings
370  *
371  *    Revision 1.35  2001/07/31 14:44:22  oes
372  *    Deleted unused size parameter from filter_popups()
373  *
374  *    Revision 1.34  2001/07/30 22:08:36  jongfoster
375  *    Tidying up #defines:
376  *    - All feature #defines are now of the form FEATURE_xxx
377  *    - Permanently turned off WIN_GUI_EDIT
378  *    - Permanently turned on WEBDAV and SPLIT_PROXY_ARGS
379  *
380  *    Revision 1.33  2001/07/29 19:32:00  jongfoster
381  *    Renaming _main() [mingw32 only] to real_main(), for ANSI compliance.
382  *
383  *    Revision 1.32  2001/07/29 18:47:05  jongfoster
384  *    Adding missing #include "loadcfg.h"
385  *
386  *    Revision 1.31  2001/07/29 12:17:48  oes
387  *    Applied pthread fix by Paul Lieverse
388  *
389  *    Revision 1.30  2001/07/25 22:57:13  jongfoster
390  *    __BEOS__ no longer overrides FEATURE_PTHREAD.
391  *    This is because FEATURE_PTHREAD will soon be widely used, so I
392  *    want to keep it simple.
393  *
394  *    Revision 1.29  2001/07/24 12:47:06  oes
395  *    Applied BeOS support update by Eugenia
396  *
397  *    Revision 1.28  2001/07/23 13:26:12  oes
398  *    Fixed bug in popup-killing for the first read that caused binary garbage to be sent between headers and body
399  *
400  *    Revision 1.27  2001/07/19 19:09:47  haroon
401  *    - Added code to take care of the situation where while processing the first
402  *      server response (which includes the server header), after finding the end
403  *      of the headers we were not looking past the end of the headers for
404  *      content modification. I enabled it for filter_popups.
405  *      Someone else should look to see if other similar operations should be
406  *      done to the discarded portion of the buffer.
407  *
408  *      Note 2001/07/20: No, the other content modification mechanisms will process
409  *                       the whole iob later anyway. --oes
410  *
411  *    Revision 1.26  2001/07/18 12:31:36  oes
412  *    cosmetics
413  *
414  *    Revision 1.25  2001/07/15 19:43:49  jongfoster
415  *    Supports POSIX threads.
416  *    Also removed some unused #includes.
417  *
418  *    Revision 1.24  2001/07/13 14:00:40  oes
419  *     - Generic content modification scheme:
420  *       Each feature has its own applicability flag that is set
421  *       from csp->action->flags.
422  *       Replaced the "filtering" int flag , by a function pointer
423  *       "content_filter" to the function that will do the content
424  *       modification. If it is != NULL, the document will be buffered
425  *       and processed through *content_filter, which must set
426  *       csp->content_length and return a modified copy of the body
427  *       or return NULL (on failiure).
428  *     - Changed csp->is_text to the more generic bitmap csp->content_type
429  *       which can currently take the valued CT_TEXT or CT_GIF
430  *     - Reformatting etc
431  *     - Removed all #ifdef PCRS
432  *
433  *    Revision 1.23  2001/07/02 02:28:25  iwanttokeepanon
434  *    Added "#ifdef ACL_FILES" conditional compilation to line 1291 to exclude
435  *    the `block_acl' call.  This prevents a compilation error when the user
436  *    does not wish to use the "ACL" feature.
437  *
438  *    Revision 1.22  2001/06/29 21:45:41  oes
439  *    Indentation, CRLF->LF, Tab-> Space
440  *
441  *    Revision 1.21  2001/06/29 13:29:36  oes
442  *    - Cleaned up, improved comments
443  *    - Unified all possible interceptors (CGI,
444  *      block, trust, fast_redirect) in one
445  *      place, with one (CGI) answer generation
446  *      mechansim. Much clearer now.
447  *    - Removed the GIF image generation, which
448  *      is now done in filters.c:block_url()
449  *    - Made error conditions like domain lookup
450  *      failiure or (various) problems while talking
451  *      to the server use cgi.c:error_response()
452  *      instead of generating HTML/HTTP in chat() (yuck!)
453  *    - Removed logentry from cancelled commit
454  *
455  *    Revision 1.20  2001/06/09 10:55:28  jongfoster
456  *    Changing BUFSIZ ==> BUFFER_SIZE
457  *
458  *    Revision 1.19  2001/06/07 23:12:52  jongfoster
459  *    Replacing function pointer in struct gateway with a directly
460  *    called function forwarded_connect().
461  *    Replacing struct gateway with struct forward_spec
462  *
463  *    Revision 1.18  2001/06/03 19:12:16  oes
464  *    introduced new cgi handling
465  *
466  *    Revision 1.17  2001/06/01 20:07:23  jongfoster
467  *    Now uses action +image-blocker{} rather than config->tinygif
468  *
469  *    Revision 1.16  2001/06/01 18:49:17  jongfoster
470  *    Replaced "list_share" with "list" - the tiny memory gain was not
471  *    worth the extra complexity.
472  *
473  *    Revision 1.15  2001/05/31 21:24:47  jongfoster
474  *    Changed "permission" to "action" throughout.
475  *    Removed DEFAULT_USER_AGENT - it must now be specified manually.
476  *    Moved vanilla wafer check into chat(), since we must now
477  *    decide whether or not to add it based on the URL.
478  *
479  *    Revision 1.14  2001/05/29 20:14:01  joergs
480  *    AmigaOS bugfix: PCRS needs a lot of stack, stacksize for child threads
481  *    increased.
482  *
483  *    Revision 1.13  2001/05/29 09:50:24  jongfoster
484  *    Unified blocklist/imagelist/permissionslist.
485  *    File format is still under discussion, but the internal changes
486  *    are (mostly) done.
487  *
488  *    Also modified interceptor behaviour:
489  *    - We now intercept all URLs beginning with one of the following
490  *      prefixes (and *only* these prefixes):
491  *        * http://i.j.b/
492  *        * http://ijbswa.sf.net/config/
493  *        * http://ijbswa.sourceforge.net/config/
494  *    - New interceptors "home page" - go to http://i.j.b/ to see it.
495  *    - Internal changes so that intercepted and fast redirect pages
496  *      are not replaced with an image.
497  *    - Interceptors now have the option to send a binary page direct
498  *      to the client. (i.e. ijb-send-banner uses this)
499  *    - Implemented show-url-info interceptor.  (Which is why I needed
500  *      the above interceptors changes - a typical URL is
501  *      "http://i.j.b/show-url-info?url=www.somesite.com/banner.gif".
502  *      The previous mechanism would not have intercepted that, and
503  *      if it had been intercepted then it then it would have replaced
504  *      it with an image.)
505  *
506  *    Revision 1.12  2001/05/27 22:17:04  oes
507  *
508  *    - re_process_buffer no longer writes the modified buffer
509  *      to the client, which was very ugly. It now returns the
510  *      buffer, which it is then written by chat.
511  *
512  *    - content_length now adjusts the Content-Length: header
513  *      for modified documents rather than crunch()ing it.
514  *      (Length info in csp->content_length, which is 0 for
515  *      unmodified documents)
516  *
517  *    - For this to work, sed() is called twice when filtering.
518  *
519  *    Revision 1.11  2001/05/26 17:27:53  jongfoster
520  *    Added support for CLF and fixed LOG_LEVEL_LOG.
521  *    Also did CRLF->LF fix of my previous patch.
522  *
523  *    Revision 1.10  2001/05/26 15:26:15  jongfoster
524  *    ACL feature now provides more security by immediately dropping
525  *    connections from untrusted hosts.
526  *
527  *    Revision 1.9  2001/05/26 00:28:36  jongfoster
528  *    Automatic reloading of config file.
529  *    Removed obsolete SIGHUP support (Unix) and Reload menu option (Win32).
530  *    Most of the global variables have been moved to a new
531  *    struct configuration_spec, accessed through csp->config->globalname
532  *    Most of the globals remaining are used by the Win32 GUI.
533  *
534  *    Revision 1.8  2001/05/25 22:43:18  jongfoster
535  *    Fixing minor memory leak and buffer overflow.
536  *
537  *    Revision 1.7  2001/05/25 22:34:30  jongfoster
538  *    Hard tabs->Spaces
539  *
540  *    Revision 1.6  2001/05/23 00:13:58  joergs
541  *    AmigaOS support fixed.
542  *
543  *    Revision 1.5  2001/05/22 18:46:04  oes
544  *
545  *    - Enabled filtering banners by size rather than URL
546  *      by adding patterns that replace all standard banner
547  *      sizes with the "Junkbuster" gif to the re_filterfile
548  *
549  *    - Enabled filtering WebBugs by providing a pattern
550  *      which kills all 1x1 images
551  *
552  *    - Added support for PCRE_UNGREEDY behaviour to pcrs,
553  *      which is selected by the (nonstandard and therefore
554  *      capital) letter 'U' in the option string.
555  *      It causes the quantifiers to be ungreedy by default.
556  *      Appending a ? turns back to greedy (!).
557  *
558  *    - Added a new interceptor ijb-send-banner, which
559  *      sends back the "Junkbuster" gif. Without imagelist or
560  *      MSIE detection support, or if tinygif = 1, or the
561  *      URL isn't recognized as an imageurl, a lame HTML
562  *      explanation is sent instead.
563  *
564  *    - Added new feature, which permits blocking remote
565  *      script redirects and firing back a local redirect
566  *      to the browser.
567  *      The feature is conditionally compiled, i.e. it
568  *      can be disabled with --disable-fast-redirects,
569  *      plus it must be activated by a "fast-redirects"
570  *      line in the config file, has its own log level
571  *      and of course wants to be displayed by show-proxy-args
572  *      Note: Boy, all the #ifdefs in 1001 locations and
573  *      all the fumbling with configure.in and acconfig.h
574  *      were *way* more work than the feature itself :-(
575  *
576  *    - Because a generic redirect template was needed for
577  *      this, tinygif = 3 now uses the same.
578  *
579  *    - Moved GIFs, and other static HTTP response templates
580  *      to project.h
581  *
582  *    - Some minor fixes
583  *
584  *    - Removed some >400 CRs again (Jon, you really worked
585  *      a lot! ;-)
586  *
587  *    Revision 1.4  2001/05/21 19:34:01  jongfoster
588  *    Made failure to bind() a fatal error.
589  *
590  *    Revision 1.3  2001/05/20 01:21:20  jongfoster
591  *    Version 2.9.4 checkin.
592  *    - Merged popupfile and cookiefile, and added control over PCRS
593  *      filtering, in new "permissionsfile".
594  *    - Implemented LOG_LEVEL_FATAL, so that if there is a configuration
595  *      file error you now get a message box (in the Win32 GUI) rather
596  *      than the program exiting with no explanation.
597  *    - Made killpopup use the PCRS MIME-type checking and HTTP-header
598  *      skipping.
599  *    - Removed tabs from "config"
600  *    - Moved duplicated url parsing code in "loaders.c" to a new funcition.
601  *    - Bumped up version number.
602  *
603  *    Revision 1.2  2001/05/17 22:34:44  oes
604  *     - Added hint on GIF char array generation to jcc.c
605  *     - Cleaned CRLF's from the sources and related files
606  *     - Repaired logging for REF and FRC
607  *
608  *    Revision 1.1.1.1  2001/05/15 13:58:56  oes
609  *    Initial import of version 2.9.3 source tree
610  *
611  *
612  *********************************************************************/
613 \f
614
615 #include "config.h"
616
617 #include <stdio.h>
618 #include <sys/types.h>
619 #include <stdlib.h>
620 #include <string.h>
621 #include <signal.h>
622 #include <fcntl.h>
623 #include <errno.h>
624
625 #ifdef FEATURE_PTHREAD
626 #include <pthread.h>
627 #endif /* def FEATURE_PTHREAD */
628
629 #ifdef _WIN32
630 # ifndef FEATURE_PTHREAD
631 #  ifndef STRICT
632 #   define STRICT
633 #  endif
634 #  include <windows.h>
635 #  include <process.h>
636 # endif /* ndef FEATURE_PTHREAD */
637
638 # include "win32.h"
639 # ifndef _WIN_CONSOLE
640 #  include "w32log.h"
641 # endif /* ndef _WIN_CONSOLE */
642
643 #else /* ifndef _WIN32 */
644
645 # if !defined (__OS2__)
646 # include <unistd.h>
647 # include <sys/wait.h>
648 # endif /* ndef __OS2__ */
649 # include <sys/time.h>
650 # include <sys/stat.h>
651 # include <sys/ioctl.h>
652
653 #ifdef sun
654 #include <sys/termios.h>
655 #endif /* sun */
656
657 #ifdef unix
658 #include <pwd.h>
659 #include <grp.h>
660 #endif
661
662 # include <signal.h>
663
664 # ifdef __BEOS__
665 #  include <socket.h>  /* BeOS has select() for sockets only. */
666 #  include <OS.h>      /* declarations for threads and stuff. */
667 # endif
668
669 # if defined(__EMX__) || defined(__OS2__)
670 #  include <sys/select.h>  /* OS/2/EMX needs a little help with select */
671 # endif
672 # ifdef __OS2__
673 #define INCL_DOS
674 # include <os2.h>
675 #define bzero(B,N) memset(B,0x00,n)
676 # endif
677
678 # ifndef FD_ZERO
679 #  include <select.h>
680 # endif
681
682 #endif
683
684 #include "project.h"
685 #include "list.h"
686 #include "jcc.h"
687 #include "filters.h"
688 #include "loaders.h"
689 #include "parsers.h"
690 #include "killpopup.h"
691 #include "miscutil.h"
692 #include "errlog.h"
693 #include "jbsockets.h"
694 #include "gateway.h"
695 #include "actions.h"
696 #include "cgi.h"
697 #include "loadcfg.h"
698 #include "urlmatch.h"
699
700 const char jcc_h_rcs[] = JCC_H_VERSION;
701 const char project_h_rcs[] = PROJECT_H_VERSION;
702
703 int no_daemon = 0;
704 struct client_state  clients[1];
705 struct file_list     files[1];
706
707 #ifdef FEATURE_STATISTICS
708 int urls_read     = 0;     /* total nr of urls read inc rejected */
709 int urls_rejected = 0;     /* total nr of urls rejected */
710 #endif /* def FEATURE_STATISTICS */
711
712 #ifdef FEATURE_GRACEFUL_TERMINATION
713 int g_terminate = 0;
714 #endif
715
716 static void listen_loop(void);
717 static void chat(struct client_state *csp);
718 #ifdef AMIGA
719 void serve(struct client_state *csp);
720 #else /* ifndef AMIGA */
721 static void serve(struct client_state *csp);
722 #endif /* def AMIGA */
723
724 #ifdef __BEOS__
725 static int32 server_thread(void *data);
726 #endif /* def __BEOS__ */
727
728 #ifdef _WIN32
729 #define sleep(N)  Sleep(((N) * 1000))
730 #endif
731
732 #ifdef __OS2__
733 #define sleep(N)  DosSleep(((N) * 100))
734 #endif
735
736 #ifdef OSX_DARWIN
737 /*
738  * Hit OSX over the head with a hammer.  Protect all *_r functions.
739  */
740 pthread_mutex_t gmtime_mutex;
741 pthread_mutex_t localtime_mutex;
742 pthread_mutex_t gethostbyaddr_mutex;
743 pthread_mutex_t gethostbyname_mutex;
744 #endif /* def OSX_DARWIN */
745
746 #ifdef FEATURE_PTHREAD
747 pthread_mutex_t log_mutex;
748 pthread_mutex_t log_init_mutex;
749 #endif /* FEATURE_PTHREAD */
750
751 #if defined(unix) || defined(__EMX__)
752 const char *basedir = NULL;
753 const char *pidfile = NULL;
754 int received_hup_signal = 0;
755 #endif /* defined unix */
756
757 /* The vanilla wafer. */
758 static const char VANILLA_WAFER[] =
759    "NOTICE=TO_WHOM_IT_MAY_CONCERN_"
760    "Do_not_send_me_any_copyrighted_information_other_than_the_"
761    "document_that_I_am_requesting_or_any_of_its_necessary_components._"
762    "In_particular_do_not_send_me_any_cookies_that_"
763    "are_subject_to_a_claim_of_copyright_by_anybody._"
764    "Take_notice_that_I_refuse_to_be_bound_by_any_license_condition_"
765    "(copyright_or_otherwise)_applying_to_any_cookie._";
766
767
768 #if !defined(_WIN32) && !defined(__OS2__) && !defined(AMIGA)
769 /*********************************************************************
770  *
771  * Function    :  sig_handler 
772  *
773  * Description :  Signal handler for different signals.
774  *                Exit gracefully on ABRT, TERM and  INT
775  *                or set a flag that will cause the errlog
776  *                to be reopened by the main thread on HUP.
777  *
778  * Parameters  :
779  *          1  :  the_signal = the signal cause this function to call
780  *
781  * Returns     :  - 
782  *
783  *********************************************************************/
784 static void sig_handler(int the_signal)
785 {
786    switch(the_signal)
787    {
788       case SIGABRT:
789       case SIGTERM:
790       case SIGINT:
791          log_error(LOG_LEVEL_INFO, "exiting by signal %d .. bye", the_signal);
792 #if defined(unix)
793          unlink(pidfile);
794 #endif /* unix */
795          exit(the_signal);
796          break;
797
798       case SIGHUP:
799          received_hup_signal = 1;
800          break;         
801
802       default:
803          /* 
804           * We shouldn't be here, unless we catch signals
805           * in main() that we can't handle here!
806           */
807          log_error(LOG_LEVEL_FATAL, "sig_handler: exiting on unexpected signal %d", the_signal);
808    }
809    return;
810
811 }
812 #endif
813
814
815 /*********************************************************************
816  *
817  * Function    :  chat
818  *
819  * Description :  Once a connection to the client has been accepted,
820  *                this function is called (via serve()) to handle the
821  *                main business of the communication.  When this
822  *                function returns, the caller must close the client
823  *                socket handle.
824  *
825  * Parameters  :
826  *          1  :  csp = Current client state (buffers, headers, etc...)
827  *
828  * Returns     :  On success, the number of bytes written are returned (zero
829  *                indicates nothing was written).  On error, -1 is returned,
830  *                and errno is set appropriately.  If count is zero and the
831  *                file descriptor refers to a regular file, 0 will be
832  *                returned without causing any other effect.  For a special
833  *                file, the results are not portable.
834  *
835  *********************************************************************/
836 static void chat(struct client_state *csp)
837 {
838 /*
839  * This next lines are a little ugly, but they simplifies the if statements
840  * below.  Basically if TOGGLE, then we want the if to test if the
841  * CSP_FLAG_TOGGLED_ON flag ist set, else we don't.  And if FEATURE_FORCE_LOAD,
842  * then we want the if to test for CSP_FLAG_FORCED , else we don't
843  */
844 #ifdef FEATURE_TOGGLE
845 #   define IS_TOGGLED_ON_AND (csp->flags & CSP_FLAG_TOGGLED_ON) &&
846 #else /* ifndef FEATURE_TOGGLE */
847 #   define IS_TOGGLED_ON_AND
848 #endif /* ndef FEATURE_TOGGLE */
849 #ifdef FEATURE_FORCE_LOAD
850 #   define IS_NOT_FORCED_AND !(csp->flags & CSP_FLAG_FORCED) &&
851 #else /* ifndef FEATURE_FORCE_LOAD */
852 #   define IS_NOT_FORCED_AND
853 #endif /* def FEATURE_FORCE_LOAD */
854
855 #define IS_ENABLED_AND   IS_TOGGLED_ON_AND IS_NOT_FORCED_AND
856
857    char buf[BUFFER_SIZE];
858    char *hdr;
859    char *p;
860    char *req;
861    fd_set rfds;
862    int n;
863    jb_socket maxfd;
864    int server_body;
865    int ms_iis5_hack = 0;
866    int byte_count = 0;
867    unsigned int socks_retries = 0;
868    const struct forward_spec * fwd;
869    struct http_request *http;
870    int len; /* for buffer sizes */
871 #ifdef FEATURE_KILL_POPUPS
872    int block_popups;         /* bool, 1==will block popups */
873    int block_popups_now = 0; /* bool, 1==currently blocking popups */
874 #endif /* def FEATURE_KILL_POPUPS */
875
876    int pcrs_filter;        /* bool, 1==will filter through pcrs */
877    int gif_deanimate;      /* bool, 1==will deanimate gifs */
878    int jpeg_inspect;       /* bool, 1==will inspect jpegs */
879
880    /* Function that does the content filtering for the current request */
881    char *(*content_filter)() = NULL;
882
883    /* Skeleton for HTTP response, if we should intercept the request */
884    struct http_response *rsp;
885
886    http = csp->http;
887
888    /*
889     * Read the client's request.  Note that since we're not using select() we
890     * could get blocked here if a client connected, then didn't say anything!
891     */
892
893    for (;;)
894    {
895       len = read_socket(csp->cfd, buf, sizeof(buf));
896
897       if (len <= 0) break;      /* error! */
898       
899       /*
900        * If there is no memory left for buffering the
901        * request, there is nothing we can do but hang up
902        */
903       if (add_to_iob(csp, buf, len))
904       {
905          return;
906       }
907
908       req = get_header(csp);
909
910       if (req == NULL)
911       {
912          break;    /* no HTTP request! */
913       }
914
915       if (*req == '\0')
916       {
917          continue;   /* more to come! */
918       }
919
920 #ifdef FEATURE_FORCE_LOAD
921       /* If this request contains the FORCE_PREFIX,
922        * better get rid of it now and set the force flag --oes
923        */
924
925       if (strstr(req, FORCE_PREFIX))
926       {
927          strclean(req, FORCE_PREFIX);
928          log_error(LOG_LEVEL_FORCE, "Enforcing request \"%s\".\n", req);
929          csp->flags |= CSP_FLAG_FORCED;
930       }
931
932 #endif /* def FEATURE_FORCE_LOAD */
933
934       parse_http_request(req, http, csp);
935       freez(req);
936       break;
937    }
938
939    if (http->cmd == NULL)
940    {
941       strcpy(buf, CHEADER);
942       write_socket(csp->cfd, buf, strlen(buf));
943
944       log_error(LOG_LEVEL_CLF, "%s - - [%T] \" \" 400 0", csp->ip_addr_str);
945
946       free_http_request(http);
947       return;
948    }
949
950    /* decide how to route the HTTP request */
951
952    if ((fwd = forward_url(http, csp)) == NULL)
953    {
954       log_error(LOG_LEVEL_FATAL, "gateway spec is NULL!?!?  This can't happen!");
955       /* Never get here - LOG_LEVEL_FATAL causes program exit */
956    }
957
958    /* build the http request to send to the server
959     * we have to do one of the following:
960     *
961     * create = use the original HTTP request to create a new
962     *          HTTP request that has either the path component
963     *          without the http://domainspec (w/path) or the
964     *          full orininal URL (w/url)
965     *          Note that the path and/or the HTTP version may
966     *          have been altered by now.
967     *
968     * connect = Open a socket to the host:port of the server
969     *           and short-circuit server and client socket.
970     *
971     * pass =  Pass the request unchanged if forwarding a CONNECT
972     *         request to a parent proxy. Note that we'll be sending
973     *         the CFAIL message ourselves if connecting to the parent
974     *         fails, but we won't send a CSUCCEED message if it works,
975     *         since that would result in a double message (ours and the
976     *         parent's). After sending the request to the parent, we simply
977     *         tunnel.
978     *
979     * here's the matrix:
980     *                        SSL
981     *                    0        1
982     *                +--------+--------+
983     *                |        |        |
984     *             0  | create | connect|
985     *                | w/path |        |
986     *  Forwarding    +--------+--------+
987     *                |        |        |
988     *             1  | create | pass   |
989     *                | w/url  |        |
990     *                +--------+--------+
991     *
992     */
993
994    /*
995     * Determine the actions for this URL
996     */
997 #ifdef FEATURE_TOGGLE
998    if (!(csp->flags & CSP_FLAG_TOGGLED_ON))
999    {
1000       /* Most compatible set of actions (i.e. none) */
1001       init_current_action(csp->action);
1002    }
1003    else
1004 #endif /* ndef FEATURE_TOGGLE */
1005    {
1006       url_actions(http, csp);
1007    }
1008
1009
1010    /*
1011     * Check if a CONNECT request is allowable:
1012     * In the absence of a +limit-connect action, allow only port 443.
1013     * If there is an action, allow whatever matches the specificaton.
1014     */
1015    if(http->ssl)
1016    {
1017       if(  ( !(csp->action->flags & ACTION_LIMIT_CONNECT) && csp->http->port != 443)
1018            || (csp->action->flags & ACTION_LIMIT_CONNECT
1019               && !match_portlist(csp->action->string[ACTION_STRING_LIMIT_CONNECT], csp->http->port)) )
1020       {
1021          if (csp->action->flags & ACTION_TREAT_FORBIDDEN_CONNECTS_LIKE_BLOCKS)
1022          {
1023             /* The response will violate the specs, but makes unblocking easier. */
1024             log_error(LOG_LEVEL_ERROR, "Marking suspicious CONNECT request from %s for blocking.",
1025                csp->ip_addr_str);
1026             csp->action->flags |= ACTION_BLOCK;
1027             http->ssl = 0;
1028          }
1029          else
1030          {
1031             strcpy(buf, CFORBIDDEN);
1032             write_socket(csp->cfd, buf, strlen(buf));
1033             log_error(LOG_LEVEL_CONNECT, "Denying suspicious CONNECT request from %s", csp->ip_addr_str);
1034             log_error(LOG_LEVEL_CLF, "%s - - [%T] \" \" 403 0", csp->ip_addr_str);
1035             return;
1036          }
1037       }
1038    }
1039
1040
1041    /*
1042     * Downgrade http version from 1.1 to 1.0 if +downgrade
1043     * action applies
1044     */
1045    if ( (http->ssl == 0)
1046      && (!strcmpic(http->ver, "HTTP/1.1"))
1047      && (csp->action->flags & ACTION_DOWNGRADE))
1048    {
1049       freez(http->ver);
1050       http->ver = strdup("HTTP/1.0");
1051
1052       if (http->ver == NULL)
1053       {
1054          log_error(LOG_LEVEL_FATAL, "Out of memory downgrading HTTP version");
1055       }
1056    }
1057
1058    /* 
1059     * Save a copy of the original request for logging
1060     */
1061    http->ocmd = strdup(http->cmd);
1062
1063    if (http->ocmd == NULL)
1064    {
1065       log_error(LOG_LEVEL_FATAL, "Out of memory copying HTTP request line");
1066    }
1067
1068    /*
1069     * (Re)build the HTTP request for non-SSL requests.
1070     * If forwarding, use the whole URL, else, use only the path.
1071     */
1072    if (http->ssl == 0)
1073    {
1074       freez(http->cmd);
1075
1076       http->cmd = strdup(http->gpc);
1077       string_append(&http->cmd, " ");
1078
1079       if (fwd->forward_host)
1080       {
1081          string_append(&http->cmd, http->url);
1082       }
1083       else
1084       {
1085          string_append(&http->cmd, http->path);
1086       }
1087       string_append(&http->cmd, " ");
1088       string_append(&http->cmd, http->ver);
1089
1090       if (http->cmd == NULL)
1091       {
1092          log_error(LOG_LEVEL_FATAL, "Out of memory writing HTTP command");
1093       }
1094       log_error(LOG_LEVEL_HEADER, "New HTTP Request-Line: %s", http->cmd);
1095    }
1096    enlist(csp->headers, http->cmd);
1097
1098
1099    /*
1100     * If the user has not supplied any wafers, and the user has not
1101     * told us to suppress the vanilla wafer, then send the vanilla wafer.
1102     */
1103    if (list_is_empty(csp->action->multi[ACTION_MULTI_WAFER])
1104        && ((csp->action->flags & ACTION_VANILLA_WAFER) != 0))
1105    {
1106       enlist(csp->action->multi[ACTION_MULTI_WAFER], VANILLA_WAFER);
1107    }
1108
1109
1110 #ifdef FEATURE_KILL_POPUPS
1111    block_popups               = ((csp->action->flags & ACTION_NO_POPUPS) != 0);
1112 #endif /* def FEATURE_KILL_POPUPS */
1113
1114    pcrs_filter                = (csp->rlist != NULL) &&  /* There are expressions to be used */
1115                                 (!list_is_empty(csp->action->multi[ACTION_MULTI_FILTER]));
1116
1117    gif_deanimate              = ((csp->action->flags & ACTION_DEANIMATE) != 0);
1118
1119    jpeg_inspect               = ((csp->action->flags & ACTION_JPEG_INSPECT) != 0);
1120
1121    /* grab the rest of the client's headers */
1122
1123    for (;;)
1124    {
1125       if ( ( ( p = get_header(csp) ) != NULL) && ( *p == '\0' ) )
1126       {
1127          len = read_socket(csp->cfd, buf, sizeof(buf));
1128          if (len <= 0)
1129          {
1130             log_error(LOG_LEVEL_ERROR, "read from client failed: %E");
1131             return;
1132          }
1133          
1134          /*
1135           * If there is no memory left for buffering the
1136           * request, there is nothing we can do but hang up
1137           */
1138          if (add_to_iob(csp, buf, len))
1139          {
1140             return;
1141          }
1142          continue;
1143       }
1144
1145       if (p == NULL) break;
1146
1147       enlist(csp->headers, p);
1148       freez(p);
1149    }
1150
1151    /*
1152     * We have a request. Now, check to see if we need to
1153     * intercept it, i.e. If ..
1154     */
1155
1156    if (
1157        /* We may not forward the request by rfc2616 sect 14.31 */
1158        (NULL != (rsp = direct_response(csp)))
1159
1160        /* or a CGI call was detected and answered */
1161        || (NULL != (rsp = dispatch_cgi(csp)))
1162
1163        /* or we are enabled and... */
1164        || (IS_ENABLED_AND (
1165
1166             /* ..the request was blocked */
1167           ( NULL != (rsp = block_url(csp)))
1168
1169           /* ..or untrusted */
1170 #ifdef FEATURE_TRUST
1171           || ( NULL != (rsp = trust_url(csp)))
1172 #endif /* def FEATURE_TRUST */
1173
1174           /* ..or a fast redirect kicked in */
1175 #ifdef FEATURE_FAST_REDIRECTS
1176           || (((csp->action->flags & ACTION_FAST_REDIRECTS) != 0) &&
1177                 (NULL != (rsp = redirect_url(csp))))
1178 #endif /* def FEATURE_FAST_REDIRECTS */
1179           ))
1180       )
1181    {
1182       /* Write the answer to the client */
1183       if (write_socket(csp->cfd, rsp->head, rsp->head_length)
1184        || write_socket(csp->cfd, rsp->body, rsp->content_length))
1185       {
1186          log_error(LOG_LEVEL_ERROR, "write to: %s failed: %E", http->host);
1187       }
1188
1189 #ifdef FEATURE_STATISTICS
1190       /* Count as a rejected request */
1191       csp->flags |= CSP_FLAG_REJECTED;
1192 #endif /* def FEATURE_STATISTICS */
1193
1194       /* Log (FIXME: All intercept reasons appear as "crunch" with Status 200) */
1195       log_error(LOG_LEVEL_GPC, "%s%s crunch!", http->hostport, http->path);
1196       log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 200 3", csp->ip_addr_str, http->ocmd);
1197
1198       /* Clean up and return */
1199       free_http_response(rsp);
1200       return;
1201    }
1202
1203    hdr = sed(client_patterns, add_client_headers, csp);
1204    if (hdr == NULL)
1205    {
1206       /* FIXME Should handle error properly */
1207       log_error(LOG_LEVEL_FATAL, "Out of memory parsing client header");
1208    }
1209
1210    list_remove_all(csp->headers);
1211
1212    log_error(LOG_LEVEL_GPC, "%s%s", http->hostport, http->path);
1213
1214    if (fwd->forward_host)
1215    {
1216       log_error(LOG_LEVEL_CONNECT, "via %s:%d to: %s",
1217                fwd->forward_host, fwd->forward_port, http->hostport);
1218    }
1219    else
1220    {
1221       log_error(LOG_LEVEL_CONNECT, "to %s", http->hostport);
1222    }
1223
1224    /* here we connect to the server, gateway, or the forwarder */
1225
1226    while ( (csp->sfd = forwarded_connect(fwd, http, csp))
1227          && (errno == EINVAL) && (socks_retries++ < 3))
1228    {
1229                 log_error(LOG_LEVEL_ERROR, "failed request #%u to connect to %s. Trying again.",
1230                 socks_retries, http->hostport);
1231    }
1232
1233    if (csp->sfd == JB_INVALID_SOCKET)
1234    {
1235       log_error(LOG_LEVEL_CONNECT, "connect to: %s failed: %E",
1236                 http->hostport);
1237
1238       if (errno == EINVAL)
1239       {
1240          rsp = error_response(csp, "no-such-domain", errno);
1241
1242          log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 404 0",
1243                    csp->ip_addr_str, http->ocmd);
1244       }
1245       else
1246       {
1247          rsp = error_response(csp, "connect-failed", errno);
1248
1249          log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 503 0",
1250                    csp->ip_addr_str, http->ocmd);
1251       }
1252
1253
1254       /* Write the answer to the client */
1255       if(rsp)
1256       {
1257          if (write_socket(csp->cfd, rsp->head, rsp->head_length)
1258           || write_socket(csp->cfd, rsp->body, rsp->content_length))
1259          {
1260             log_error(LOG_LEVEL_ERROR, "write to: %s failed: %E", http->host);
1261          }
1262       }
1263
1264       free_http_response(rsp);
1265       freez(hdr);
1266       return;
1267    }
1268
1269    log_error(LOG_LEVEL_CONNECT, "OK");
1270
1271    if (fwd->forward_host || (http->ssl == 0))
1272    {
1273       /* write the client's (modified) header to the server
1274        * (along with anything else that may be in the buffer)
1275        */
1276
1277       if (write_socket(csp->sfd, hdr, strlen(hdr))
1278        || (flush_socket(csp->sfd, csp) <  0))
1279       {
1280          log_error(LOG_LEVEL_CONNECT, "write header to: %s failed: %E",
1281                     http->hostport);
1282
1283          log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 503 0",
1284                    csp->ip_addr_str, http->ocmd);
1285
1286          rsp = error_response(csp, "connect-failed", errno);
1287
1288          if(rsp)
1289          {
1290             if (write_socket(csp->cfd, rsp->head, rsp->head_length)
1291              || write_socket(csp->cfd, rsp->body, rsp->content_length))
1292             {
1293                log_error(LOG_LEVEL_ERROR, "write to: %s failed: %E", http->host);
1294             }
1295          }
1296
1297          free_http_response(rsp);
1298          freez(hdr);
1299          return;
1300       }
1301    }
1302    else
1303    {
1304       /*
1305        * We're running an SSL tunnel and we're not forwarding,
1306        * so just send the "connect succeeded" message to the
1307        * client, flush the rest, and get out of the way.
1308        */
1309       log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 200 2\n",
1310                 csp->ip_addr_str, http->ocmd);
1311
1312       if (write_socket(csp->cfd, CSUCCEED, sizeof(CSUCCEED)-1))
1313       {
1314          freez(hdr);
1315          return;
1316       }
1317       IOB_RESET(csp);
1318    }
1319
1320    /* we're finished with the client's header */
1321    freez(hdr);
1322
1323    maxfd = ( csp->cfd > csp->sfd ) ? csp->cfd : csp->sfd;
1324
1325    /* pass data between the client and server
1326     * until one or the other shuts down the connection.
1327     */
1328
1329    server_body = 0;
1330
1331    for (;;)
1332    {
1333 #ifdef __OS2__
1334       /*
1335        * FD_ZERO here seems to point to an errant macro which crashes.
1336        * So do this by hand for now...
1337        */
1338       memset(&rfds,0x00,sizeof(fd_set));
1339 #else
1340       FD_ZERO(&rfds);
1341 #endif
1342       FD_SET(csp->cfd, &rfds);
1343       FD_SET(csp->sfd, &rfds);
1344
1345       n = select((int)maxfd+1, &rfds, NULL, NULL, NULL);
1346
1347       if (n < 0)
1348       {
1349          log_error(LOG_LEVEL_ERROR, "select() failed!: %E");
1350          return;
1351       }
1352
1353       /* this is the body of the browser's request
1354        * just read it and write it.
1355        */
1356
1357       if (FD_ISSET(csp->cfd, &rfds))
1358       {
1359          len = read_socket(csp->cfd, buf, sizeof(buf));
1360
1361          if (len <= 0)
1362          {
1363             break; /* "game over, man" */
1364          }
1365
1366          if (write_socket(csp->sfd, buf, (size_t)len))
1367          {
1368             log_error(LOG_LEVEL_ERROR, "write to: %s failed: %E", http->host);
1369             return;
1370          }
1371          continue;
1372       }
1373
1374       /*
1375        * The server wants to talk.  It could be the header or the body.
1376        * If `hdr' is null, then it's the header otherwise it's the body.
1377        * FIXME: Does `hdr' really mean `host'? No.
1378        */
1379
1380
1381       if (FD_ISSET(csp->sfd, &rfds))
1382       {
1383          fflush( 0 );
1384          len = read_socket(csp->sfd, buf, sizeof(buf) - 1);
1385
1386          if (len < 0)
1387          {
1388             log_error(LOG_LEVEL_ERROR, "read from: %s failed: %E", http->host);
1389
1390             log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 503 0",
1391                       csp->ip_addr_str, http->ocmd);
1392
1393             rsp = error_response(csp, "connect-failed", errno);
1394
1395             if(rsp)
1396             {
1397                if (write_socket(csp->cfd, rsp->head, rsp->head_length)
1398                 || write_socket(csp->cfd, rsp->body, rsp->content_length))
1399                {
1400                   log_error(LOG_LEVEL_ERROR, "write to: %s failed: %E", http->host);
1401                }
1402             }
1403
1404             free_http_response(rsp);
1405             return;
1406          }
1407
1408          /* Add a trailing zero.  This lets filter_popups
1409           * use string operations.
1410           */
1411          buf[len] = '\0';
1412
1413 #ifdef FEATURE_KILL_POPUPS
1414          /* Filter the popups on this read. */
1415          if (block_popups_now)
1416          {
1417             filter_popups(buf, csp);
1418          }
1419 #endif /* def FEATURE_KILL_POPUPS */
1420
1421          /* Normally, this would indicate that we've read
1422           * as much as the server has sent us and we can
1423           * close the client connection.  However, Microsoft
1424           * in its wisdom has released IIS/5 with a bug that
1425           * prevents it from sending the trailing \r\n in
1426           * a 302 redirect header (and possibly other headers).
1427           * To work around this if we've haven't parsed
1428           * a full header we'll append a trailing \r\n
1429           * and see if this now generates a valid one.
1430           *
1431           * This hack shouldn't have any impacts.  If we've
1432           * already transmitted the header or if this is a
1433           * SSL connection, then we won't bother with this
1434           * hack.  So we only work on partially received
1435           * headers.  If we append a \r\n and this still
1436           * doesn't generate a valid header, then we won't
1437           * transmit anything to the client.
1438           */
1439          if (len == 0)
1440          {
1441
1442             if (server_body || http->ssl)
1443             {
1444                /*
1445                 * If we have been buffering up the document,
1446                 * now is the time to apply content modification
1447                 * and send the result to the client.
1448                 */
1449                if (content_filter)
1450                {
1451                   /*
1452                    * If the content filter fails, use the original
1453                    * buffer and length.
1454                    * (see p != NULL ? p : csp->iob->cur below)
1455                    */
1456                   if (NULL == (p = (*content_filter)(csp)))
1457                   {
1458                      csp->content_length = csp->iob->eod - csp->iob->cur;
1459                   }
1460
1461                   hdr = sed(server_patterns_light, NULL, csp);
1462
1463                   if (hdr == NULL)
1464                   {
1465                      /* FIXME Should handle error properly */
1466                      log_error(LOG_LEVEL_FATAL, "Out of memory parsing server header");
1467                   }
1468
1469                   if (write_socket(csp->cfd, hdr, strlen(hdr))
1470                    || write_socket(csp->cfd, p != NULL ? p : csp->iob->cur, csp->content_length))
1471                   {
1472                      log_error(LOG_LEVEL_ERROR, "write modified content to client failed: %E");
1473                      freez(hdr);
1474                      freez(p);
1475                      return;
1476                   }
1477
1478                   freez(hdr);
1479                   freez(p);
1480                }
1481
1482                break; /* "game over, man" */
1483             }
1484
1485             /*
1486              * This is NOT the body, so
1487              * Let's pretend the server just sent us a blank line.
1488              */
1489             len = sprintf(buf, "\r\n");
1490
1491             /*
1492              * Now, let the normal header parsing algorithm below do its
1493              * job.  If it fails, we'll exit instead of continuing.
1494              */
1495
1496             ms_iis5_hack = 1;
1497          }
1498
1499          /*
1500           * If this is an SSL connection or we're in the body
1501           * of the server document, just write it to the client,
1502           * unless we need to buffer the body for later content-filtering
1503           */
1504
1505          if (server_body || http->ssl)
1506          {
1507             if (content_filter)
1508             {
1509                /*
1510                 * If there is no memory left for buffering the content, or the buffer limit
1511                 * has been reached, switch to non-filtering mode, i.e. make & write the
1512                 * header, flush the iob and buf, and get out of the way.
1513                 */
1514                if (add_to_iob(csp, buf, len))
1515                {
1516                   size_t hdrlen;
1517                   int flushed;
1518
1519                   log_error(LOG_LEVEL_ERROR, "Flushing header and buffers. Stepping back from filtering.");
1520
1521                   hdr = sed(server_patterns, add_server_headers, csp);
1522                   if (hdr == NULL)
1523                   {
1524                      /* 
1525                       * Memory is too tight to even generate the header.
1526                       * Send our static "Out-of-memory" page.
1527                       */
1528                      log_error(LOG_LEVEL_ERROR, "Out of memory while trying to flush.");
1529                      rsp = cgi_error_memory();
1530
1531                      if (write_socket(csp->cfd, rsp->head, rsp->head_length)
1532                          || write_socket(csp->cfd, rsp->body, rsp->content_length))
1533                      {
1534                         log_error(LOG_LEVEL_ERROR, "write to: %s failed: %E", http->host);
1535                      }
1536                      return;
1537                   }
1538
1539                   hdrlen = strlen(hdr);
1540
1541                   if (write_socket(csp->cfd, hdr, hdrlen)
1542                    || ((flushed = flush_socket(csp->cfd, csp)) < 0)
1543                    || (write_socket(csp->cfd, buf, (size_t) len)))
1544                   {
1545                      log_error(LOG_LEVEL_CONNECT, "Flush header and buffers to client failed: %E");
1546
1547                      freez(hdr);
1548                      return;
1549                   }
1550
1551                   byte_count += hdrlen + flushed + len;
1552                   freez(hdr);
1553                   content_filter = NULL;
1554                   server_body = 1;
1555
1556                }
1557             }
1558             else
1559             {
1560                if (write_socket(csp->cfd, buf, (size_t)len))
1561                {
1562                   log_error(LOG_LEVEL_ERROR, "write to client failed: %E");
1563                   return;
1564                }
1565             }
1566             byte_count += len;
1567             continue;
1568          }
1569          else
1570          {
1571             /* we're still looking for the end of the
1572              * server's header ... (does that make header
1573              * parsing an "out of body experience" ?
1574              */
1575
1576             /* 
1577              * buffer up the data we just read.  If that fails, 
1578              * there's little we can do but send our static
1579              * out-of-memory page.
1580              */
1581             if (add_to_iob(csp, buf, len))
1582             {
1583                log_error(LOG_LEVEL_ERROR, "Out of memory while looking for end of server headers.");
1584                rsp = cgi_error_memory();
1585                
1586                if (write_socket(csp->cfd, rsp->head, rsp->head_length)
1587                    || write_socket(csp->cfd, rsp->body, rsp->content_length))
1588                {
1589                   log_error(LOG_LEVEL_ERROR, "write to: %s failed: %E", http->host);
1590                }
1591                return;
1592             }
1593
1594             /* get header lines from the iob */
1595
1596             while ((p = get_header(csp)) != NULL)
1597             {
1598                if (*p == '\0')
1599                {
1600                   /* see following note */
1601                   break;
1602                }
1603                enlist(csp->headers, p);
1604                freez(p);
1605             }
1606
1607             /* NOTE: there are no "empty" headers so
1608              * if the pointer `p' is not NULL we must
1609              * assume that we reached the end of the
1610              * buffer before we hit the end of the header.
1611              */
1612
1613             if (p)
1614             {
1615                if (ms_iis5_hack)
1616                {
1617                   /* Well, we tried our MS IIS/5
1618                    * hack and it didn't work.
1619                    * The header is incomplete
1620                    * and there isn't anything
1621                    * we can do about it.
1622                    */
1623                   break;
1624                }
1625                else
1626                {
1627                   /* Since we have to wait for
1628                    * more from the server before
1629                    * we can parse the headers
1630                    * we just continue here.
1631                    */
1632                   continue;
1633                }
1634             }
1635
1636             /* we have now received the entire header.
1637              * filter it and send the result to the client
1638              */
1639
1640             hdr = sed(server_patterns, add_server_headers, csp);
1641             if (hdr == NULL)
1642             {
1643                /* FIXME Should handle error properly */
1644                log_error(LOG_LEVEL_FATAL, "Out of memory parsing server header");
1645             }
1646
1647 #ifdef FEATURE_KILL_POPUPS
1648             /* Start blocking popups if appropriate. */
1649
1650             if ((csp->content_type & CT_TEXT) &&  /* It's a text / * MIME-Type */
1651                 !http->ssl    &&                  /* We talk plaintext */
1652                 block_popups)                     /* Policy allows */
1653             {
1654                block_popups_now = 1;
1655                /*
1656                 * Filter the part of the body that came in the same read
1657                 * as the last headers:
1658                 */
1659                filter_popups(csp->iob->cur, csp);
1660             }
1661
1662 #endif /* def FEATURE_KILL_POPUPS */
1663
1664             /* Buffer and pcrs filter this if appropriate. */
1665
1666             if ((csp->content_type & CT_TEXT) &&  /* It's a text / * MIME-Type */
1667                 !http->ssl    &&                  /* We talk plaintext */
1668                 pcrs_filter)                      /* Policy allows */
1669             {
1670                content_filter = pcrs_filter_response;
1671             }
1672
1673             /* Buffer and gif_deanimate this if appropriate. */
1674
1675             if ((csp->content_type & CT_GIF)  &&  /* It's an image/gif MIME-Type */
1676                 !http->ssl    &&                  /* We talk plaintext */
1677                 gif_deanimate)                    /* Policy allows */
1678             {
1679                content_filter = gif_deanimate_response;
1680             }
1681
1682             /* Buffer and jpg_inspect this if appropriate. */
1683
1684             if ((csp->content_type & CT_JPEG)  &&  /* It's an image/jpeg MIME-Type */
1685                 !http->ssl    &&                   /* We talk plaintext */
1686                 jpeg_inspect)                      /* Policy allows */
1687             {
1688                content_filter = jpeg_inspect_response;
1689             }
1690
1691             /*
1692              * Only write if we're not buffering for content modification
1693              */
1694             if (!content_filter)
1695             {
1696                /* write the server's (modified) header to
1697                 * the client (along with anything else that
1698                 * may be in the buffer)
1699                 */
1700
1701                if (write_socket(csp->cfd, hdr, strlen(hdr))
1702                 || ((len = flush_socket(csp->cfd, csp)) < 0))
1703                {
1704                   log_error(LOG_LEVEL_CONNECT, "write header to client failed: %E");
1705
1706                   /* the write failed, so don't bother
1707                    * mentioning it to the client...
1708                    * it probably can't hear us anyway.
1709                    */
1710                   freez(hdr);
1711                   return;
1712                }
1713
1714                byte_count += len;
1715             }
1716
1717             /* we're finished with the server's header */
1718
1719             freez(hdr);
1720             server_body = 1;
1721
1722             /* If this was a MS IIS/5 hack then it means
1723              * the server has already closed the
1724              * connection.  Nothing more to read.  Time
1725              * to bail.
1726              */
1727             if (ms_iis5_hack)
1728             {
1729                break;
1730             }
1731          }
1732          continue;
1733       }
1734
1735       return; /* huh? we should never get here */
1736    }
1737
1738    log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 200 %d",
1739              csp->ip_addr_str, http->ocmd, byte_count);
1740 }
1741
1742
1743 /*********************************************************************
1744  *
1745  * Function    :  serve
1746  *
1747  * Description :  This is little more than chat.  We only "serve" to
1748  *                to close any socket that chat may have opened.
1749  *
1750  * Parameters  :
1751  *          1  :  csp = Current client state (buffers, headers, etc...)
1752  *
1753  * Returns     :  N/A
1754  *
1755  *********************************************************************/
1756 #ifdef AMIGA
1757 void serve(struct client_state *csp)
1758 #else /* ifndef AMIGA */
1759 static void serve(struct client_state *csp)
1760 #endif /* def AMIGA */
1761 {
1762    chat(csp);
1763    close_socket(csp->cfd);
1764
1765    if (csp->sfd != JB_INVALID_SOCKET)
1766    {
1767       close_socket(csp->sfd);
1768    }
1769
1770    csp->flags &= ~CSP_FLAG_ACTIVE;
1771
1772 }
1773
1774
1775 #ifdef __BEOS__
1776 /*********************************************************************
1777  *
1778  * Function    :  server_thread
1779  *
1780  * Description :  We only exist to call `serve' in a threaded environment.
1781  *
1782  * Parameters  :
1783  *          1  :  data = Current client state (buffers, headers, etc...)
1784  *
1785  * Returns     :  Always 0.
1786  *
1787  *********************************************************************/
1788 static int32 server_thread(void *data)
1789 {
1790    serve((struct client_state *) data);
1791    return 0;
1792
1793 }
1794 #endif
1795
1796
1797 /*********************************************************************
1798  *
1799  * Function    :  usage
1800  *
1801  * Description :  Print usage info & exit.
1802  *
1803  * Parameters  :  Pointer to argv[0] for identifying ourselves
1804  *
1805  * Returns     :  No. ,-)
1806  *
1807  *********************************************************************/
1808 void usage(const char *myname)
1809 {
1810    printf("Privoxy version " VERSION " (" HOME_PAGE_URL ")\n"
1811 #if !defined(unix)
1812            "Usage: %s [--help] [--version] [configfile]\n"
1813 #else
1814            "Usage: %s [--help] [--version] [--no-daemon] [--pidfile pidfile] [--user user[.group]] [configfile]\n"
1815 #endif
1816            "Aborting.\n", myname);
1817  
1818    exit(2);
1819
1820 }
1821
1822
1823 /*********************************************************************
1824  *
1825  * Function    :  main
1826  *
1827  * Description :  Load the config file and start the listen loop.
1828  *                This function is a lot more *sane* with the `load_config'
1829  *                and `listen_loop' functions; although it stills does
1830  *                a *little* too much for my taste.
1831  *
1832  * Parameters  :
1833  *          1  :  argc = Number of parameters (including $0).
1834  *          2  :  argv = Array of (char *)'s to the parameters.
1835  *
1836  * Returns     :  1 if : can't open config file, unrecognized directive,
1837  *                stats requested in multi-thread mode, can't open the
1838  *                log file, can't open the jar file, listen port is invalid,
1839  *                any load fails, and can't bind port.
1840  *
1841  *                Else main never returns, the process must be signaled
1842  *                to terminate execution.  Or, on Windows, use the
1843  *                "File", "Exit" menu option.
1844  *
1845  *********************************************************************/
1846 #ifdef __MINGW32__
1847 int real_main(int argc, const char *argv[])
1848 #else
1849 int main(int argc, const char *argv[])
1850 #endif
1851 {
1852    int argc_pos = 0;
1853 #ifdef unix
1854    struct passwd *pw = NULL;
1855    struct group *grp = NULL;
1856    char *p;
1857    int do_chroot = 0;
1858 #endif
1859
1860    Argc = argc;
1861    Argv = argv;
1862
1863    configfile =
1864 #if !defined(_WIN32)
1865    "config"
1866 #else
1867    "config.txt"
1868 #endif
1869       ;
1870
1871    /*
1872     * Parse the command line arguments
1873     */
1874    while (++argc_pos < argc)
1875    {
1876       if (strcmp(argv[argc_pos], "--help") == 0)
1877       {
1878          usage(argv[0]);
1879       }
1880
1881       else if(strcmp(argv[argc_pos], "--version") == 0)
1882       {
1883          printf("Privoxy version " VERSION " (" HOME_PAGE_URL ")\n");
1884          exit(0);
1885       }
1886
1887 #if defined(unix)
1888
1889      else if (strcmp(argv[argc_pos], "--no-daemon" ) == 0)
1890       {
1891          no_daemon = 1;
1892       }
1893
1894       else if (strcmp(argv[argc_pos], "--pidfile" ) == 0)
1895       {
1896          if (++argc_pos == argc) usage(argv[0]);
1897          pidfile = strdup(argv[argc_pos]);
1898       }
1899
1900       else if (strcmp(argv[argc_pos], "--user" ) == 0)
1901       {
1902          if (++argc_pos == argc) usage(argv[argc_pos]);
1903
1904          if ((NULL != (p = strchr(argv[argc_pos], '.'))) && *(p + 1) != '0')
1905          {
1906             *p++ = '\0';
1907             if (NULL == (grp = getgrnam(p)))
1908             {
1909                log_error(LOG_LEVEL_FATAL, "Group %s not found.", p);
1910             }
1911          }
1912
1913          if (NULL == (pw = getpwnam(argv[argc_pos])))
1914          {
1915             log_error(LOG_LEVEL_FATAL, "User %s not found.", argv[argc_pos]);
1916          }
1917
1918          if (p != NULL) *--p = '\0';
1919       }
1920
1921       else if (strcmp(argv[argc_pos], "--chroot" ) == 0)
1922       {
1923          do_chroot = 1;
1924       }
1925
1926 #endif /* defined(unix) */
1927
1928       else
1929       {
1930          configfile = argv[argc_pos];
1931       }
1932
1933    } /* -END- while (more arguments) */
1934
1935 #if defined(unix)
1936    if ( *configfile != '/' )
1937    {
1938       char *abs_file, cwd[1024];
1939
1940       /* make config-filename absolute here */
1941       if ( !(getcwd(cwd, sizeof(cwd))))
1942       {
1943          perror("get working dir failed");
1944          exit( 1 );
1945       }
1946
1947       if (!(basedir = strdup(cwd))
1948       || (!(abs_file = malloc( strlen( basedir ) + strlen( configfile ) + 5 ))))
1949       {
1950          perror("malloc failed");
1951          exit( 1 );
1952       }
1953       strcpy( abs_file, basedir );
1954       strcat( abs_file, "/" );
1955       strcat( abs_file, configfile );
1956       configfile = abs_file;
1957    }
1958 #endif /* defined unix */
1959
1960
1961    files->next = NULL;
1962    clients->next = NULL;
1963
1964 #ifdef AMIGA
1965    InitAmiga();
1966 #elif defined(_WIN32)
1967    InitWin32();
1968 #endif
1969
1970 #ifdef OSX_DARWIN
1971    /*
1972     * Prepare global mutex semaphores
1973     */
1974    pthread_mutex_init(&gmtime_mutex,0);
1975    pthread_mutex_init(&localtime_mutex,0);
1976    pthread_mutex_init(&gethostbyaddr_mutex,0);
1977    pthread_mutex_init(&gethostbyname_mutex,0);
1978 #endif /* def OSX_DARWIN */
1979
1980 #ifdef FEATURE_PTHREAD
1981    pthread_mutex_init(&log_mutex,0);
1982    pthread_mutex_init(&log_init_mutex,0);
1983 #endif /* FEATURE_PTHREAD */
1984
1985    /*
1986     * Unix signal handling
1987     *
1988     * Catch the abort, interrupt and terminate signals for a graceful exit
1989     * Catch the hangup signal so the errlog can be reopened.
1990     * Ignore the broken pipe signals (FIXME: Why?)
1991     */
1992 #if !defined(_WIN32) && !defined(__OS2__) && !defined(AMIGA)
1993 {
1994    int idx;
1995    const int catched_signals[] = { SIGABRT, SIGTERM, SIGINT, SIGHUP, 0 };
1996    const int ignored_signals[] = { SIGPIPE, 0 };
1997
1998    for (idx = 0; catched_signals[idx] != 0; idx++)
1999    {
2000       if (signal(catched_signals[idx], sig_handler) == SIG_ERR)
2001       {
2002          log_error(LOG_LEVEL_FATAL, "Can't set signal-handler for signal %d: %E", catched_signals[idx]);
2003       }
2004    }
2005
2006    for (idx = 0; ignored_signals[idx] != 0; idx++)
2007    {
2008       if (signal(ignored_signals[idx], SIG_IGN) == SIG_ERR)
2009       {
2010          log_error(LOG_LEVEL_FATAL, "Can't set ignore-handler for signal %d: %E", ignored_signals[idx]);
2011       }
2012    }
2013
2014 }
2015 #else /* ifdef _WIN32 */
2016 # ifdef _WIN_CONSOLE
2017    /*
2018     * We *are* in a windows console app.
2019     * Print a verbose messages about FAQ's and such
2020     */
2021    printf(win32_blurb);
2022 # endif /* def _WIN_CONSOLE */
2023 #endif /* def _WIN32 */
2024
2025
2026    /* Initialize the CGI subsystem */
2027    cgi_init_error_messages();
2028
2029    /*
2030     * If runnig on unix and without the --nodaemon
2031     * option, become a daemon. I.e. fork, detach
2032     * from tty and get process group leadership
2033     */
2034 #if defined(unix)
2035 {
2036    pid_t pid = 0;
2037 #if 0
2038    int   fd;
2039 #endif
2040
2041    if (!no_daemon)
2042    {
2043       pid  = fork();
2044
2045       if ( pid < 0 ) /* error */
2046       {
2047          perror("fork");
2048          exit( 3 );
2049       }
2050       else if ( pid != 0 ) /* parent */
2051       {
2052          int status;
2053          pid_t wpid;
2054          /*
2055           * must check for errors
2056           * child died due to missing files aso
2057           */
2058          sleep( 1 );
2059          wpid = waitpid( pid, &status, WNOHANG );
2060          if ( wpid != 0 )
2061          {
2062             exit( 1 );
2063          }
2064          exit( 0 );
2065       }
2066       /* child */
2067 #if 1
2068       /* Should be more portable, but not as well tested */
2069       setsid();
2070 #else /* !1 */
2071 #ifdef __FreeBSD__
2072       setpgrp(0,0);
2073 #else /* ndef __FreeBSD__ */
2074       setpgrp();
2075 #endif /* ndef __FreeBSD__ */
2076       fd = open("/dev/tty", O_RDONLY);
2077       if ( fd )
2078       {
2079          /* no error check here */
2080          ioctl( fd, TIOCNOTTY,0 );
2081          close ( fd );
2082       }
2083 #endif /* 1 */
2084       /* FIXME: should close stderr (fd 2) here too, but the test
2085        * for existence
2086        * and load config file is done in listen_loop() and puts
2087        * some messages on stderr there.
2088        */
2089
2090       close( 0 );
2091       close( 1 );
2092       chdir("/");
2093
2094    } /* -END- if (!no_daemon) */
2095
2096    /*
2097     * As soon as we have written the PID file, we can switch
2098     * to the user and group ID indicated by the --user option
2099     */
2100    write_pid_file();
2101    
2102    if (NULL != pw)
2103    {
2104       if (((NULL != grp) && setgid(grp->gr_gid)) || (setgid(pw->pw_gid)))
2105       {
2106          log_error(LOG_LEVEL_FATAL, "Cannot setgid(): Insufficient permissions.");
2107       }
2108       if (do_chroot)
2109       {
2110          if (!pw->pw_dir)
2111          {
2112             log_error(LOG_LEVEL_FATAL, "Home directory for %s undefined", pw->pw_name);
2113          }
2114          if (chroot(pw->pw_dir) < 0)
2115          {
2116             log_error(LOG_LEVEL_FATAL, "Cannot chroot to %s", pw->pw_dir);
2117          }
2118          if (chdir ("/"))
2119          {
2120             log_error(LOG_LEVEL_FATAL, "Cannot chdir /");
2121          }
2122       }
2123       if (setuid(pw->pw_uid))
2124       {
2125          log_error(LOG_LEVEL_FATAL, "Cannot setuid(): Insufficient permissions.");
2126       }
2127       if (do_chroot)
2128       {
2129          char putenv_dummy[64];
2130
2131          strcpy(putenv_dummy, "HOME=/");
2132          if (putenv(putenv_dummy) != 0)
2133          {
2134             log_error(LOG_LEVEL_FATAL, "Cannot putenv(): HOME");
2135          }                
2136
2137          snprintf(putenv_dummy, 64, "USER=%s", pw->pw_name);
2138          if (putenv(putenv_dummy) != 0)
2139          {
2140             log_error(LOG_LEVEL_FATAL, "Cannot putenv(): USER");
2141          }
2142       }
2143    }
2144    else if (do_chroot)
2145    {
2146       log_error(LOG_LEVEL_FATAL, "Cannot chroot without --user argument.");
2147    }
2148 }
2149 #endif /* defined unix */
2150
2151    listen_loop();
2152
2153    /* NOTREACHED */
2154    return(-1);
2155
2156 }
2157
2158
2159 /*********************************************************************
2160  *
2161  * Function    :  bind_port_helper
2162  *
2163  * Description :  Bind the listen port.  Handles logging, and aborts
2164  *                on failure.
2165  *
2166  * Parameters  :
2167  *          1  :  config = Privoxy configuration.  Specifies port
2168  *                         to bind to.
2169  *
2170  * Returns     :  Port that was opened.
2171  *
2172  *********************************************************************/
2173 static jb_socket bind_port_helper(struct configuration_spec * config)
2174 {
2175    int result;
2176    jb_socket bfd;
2177
2178    if ( (config->haddr != NULL)
2179      && (config->haddr[0] == '1')
2180      && (config->haddr[1] == '2')
2181      && (config->haddr[2] == '7')
2182      && (config->haddr[3] == '.') )
2183    {
2184       log_error(LOG_LEVEL_INFO, "Listening on port %d for local connections only",
2185                 config->hport);
2186    }
2187    else if (config->haddr == NULL)
2188    {
2189       log_error(LOG_LEVEL_INFO, "Listening on port %d on all IP addresses",
2190                 config->hport);
2191    }
2192    else
2193    {
2194       log_error(LOG_LEVEL_INFO, "Listening on port %d on IP address %s",
2195                 config->hport, config->haddr);
2196    }
2197
2198    result = bind_port(config->haddr, config->hport, &bfd);
2199
2200    if (result < 0)
2201    {
2202       switch(result)
2203       {
2204          case -3 :
2205             log_error(LOG_LEVEL_FATAL, "can't bind to %s:%d: "
2206                "There may be another Privoxy or some other "
2207                "proxy running on port %d",
2208                (NULL != config->haddr) ? config->haddr : "INADDR_ANY",
2209                       config->hport, config->hport);
2210
2211          case -2 :
2212             log_error(LOG_LEVEL_FATAL, "can't bind to %s:%d: " 
2213                "The hostname is not resolvable",
2214                (NULL != config->haddr) ? config->haddr : "INADDR_ANY", config->hport);
2215
2216          default :
2217             log_error(LOG_LEVEL_FATAL, "can't bind to %s:%d: because %E",
2218                (NULL != config->haddr) ? config->haddr : "INADDR_ANY", config->hport);
2219       }
2220
2221       /* shouldn't get here */
2222       return JB_INVALID_SOCKET;
2223    }
2224
2225    config->need_bind = 0;
2226
2227    return bfd;
2228 }
2229
2230
2231 /*********************************************************************
2232  *
2233  * Function    :  listen_loop
2234  *
2235  * Description :  bind the listen port and enter a "FOREVER" listening loop.
2236  *
2237  * Parameters  :  N/A
2238  *
2239  * Returns     :  Never.
2240  *
2241  *********************************************************************/
2242 static void listen_loop(void)
2243 {
2244    struct client_state *csp = NULL;
2245    jb_socket bfd;
2246    struct configuration_spec * config;
2247
2248    config = load_config();
2249
2250    bfd = bind_port_helper(config);
2251
2252 #ifdef FEATURE_GRACEFUL_TERMINATION
2253    while (!g_terminate)
2254 #else
2255    for (;;)
2256 #endif
2257    {
2258 #if !defined(FEATURE_PTHREAD) && !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__)
2259       while (waitpid(-1, NULL, WNOHANG) > 0)
2260       {
2261          /* zombie children */
2262       }
2263 #endif /* !defined(FEATURE_PTHREAD) && !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) */
2264
2265       /*
2266        * Free data that was used by died threads
2267        */
2268       sweep();
2269
2270 #if defined(unix)
2271       /*
2272        * Re-open the errlog after HUP signal
2273        */
2274       if (received_hup_signal)
2275       {
2276          init_error_log(Argv[0], config->logfile, config->debug);
2277          received_hup_signal = 0;
2278       }
2279 #endif
2280
2281 #ifdef __OS2__
2282 #ifdef FEATURE_COOKIE_JAR
2283       /*
2284        * Need a workaround here: we have to fclose() the jarfile, or we die because it's
2285        * already open.  I think unload_configfile() is not being run, which should do
2286        * this work.  Until that can get resolved, we'll use this workaround.
2287        */
2288        if (csp)
2289          if(csp->config)
2290            if (csp->config->jar)
2291            {
2292              fclose(csp->config->jar);
2293              csp->config->jar = NULL;
2294            }
2295 #endif /* FEATURE_COOKIE_JAR */
2296 #endif /* __OS2__ */
2297
2298       if ( NULL == (csp = (struct client_state *) zalloc(sizeof(*csp))) )
2299       {
2300          log_error(LOG_LEVEL_FATAL, "malloc(%d) for csp failed: %E", sizeof(*csp));
2301          continue;
2302       }
2303
2304       csp->flags |= CSP_FLAG_ACTIVE;
2305       csp->sfd    = JB_INVALID_SOCKET;
2306
2307       csp->config = config = load_config();
2308
2309       if ( config->need_bind )
2310       {
2311          /*
2312           * Since we were listening to the "old port", we will not see
2313           * a "listen" param change until the next IJB request.  So, at
2314           * least 1 more request must be made for us to find the new
2315           * setting.  I am simply closing the old socket and binding the
2316           * new one.
2317           *
2318           * Which-ever is correct, we will serve 1 more page via the
2319           * old settings.  This should probably be a "show-proxy-args"
2320           * request.  This should not be a so common of an operation
2321           * that this will hurt people's feelings.
2322           */
2323
2324          close_socket(bfd);
2325
2326          bfd = bind_port_helper(config);
2327       }
2328
2329       log_error(LOG_LEVEL_CONNECT, "accept connection ... ");
2330
2331       if (!accept_connection(csp, bfd))
2332       {
2333          log_error(LOG_LEVEL_CONNECT, "accept failed: %E");
2334
2335 #ifdef AMIGA
2336          if(!childs)
2337          {
2338             exit(1);
2339          }
2340 #endif
2341          freez(csp);
2342          continue;
2343       }
2344       else
2345       {
2346          log_error(LOG_LEVEL_CONNECT, "OK");
2347       }
2348
2349 #ifdef FEATURE_TOGGLE
2350       if (global_toggle_state)
2351       {
2352          csp->flags |= CSP_FLAG_TOGGLED_ON;
2353       }
2354 #endif /* def FEATURE_TOGGLE */
2355
2356       if (run_loader(csp))
2357       {
2358          log_error(LOG_LEVEL_FATAL, "a loader failed - must exit");
2359          /* Never get here - LOG_LEVEL_FATAL causes program exit */
2360       }
2361
2362 #ifdef FEATURE_ACL
2363       if (block_acl(NULL,csp))
2364       {
2365          log_error(LOG_LEVEL_CONNECT, "Connection dropped due to ACL");
2366          close_socket(csp->cfd);
2367          freez(csp);
2368          continue;
2369       }
2370 #endif /* def FEATURE_ACL */
2371
2372       /* add it to the list of clients */
2373       csp->next = clients->next;
2374       clients->next = csp;
2375
2376       if (config->multi_threaded)
2377       {
2378          int child_id;
2379
2380 /* this is a switch () statment in the C preprocessor - ugh */
2381 #undef SELECTED_ONE_OPTION
2382
2383 /* Use Pthreads in preference to native code */
2384 #if defined(FEATURE_PTHREAD) && !defined(SELECTED_ONE_OPTION)
2385 #define SELECTED_ONE_OPTION
2386          {
2387             pthread_t the_thread;
2388             pthread_attr_t attrs;
2389
2390             pthread_attr_init(&attrs);
2391             pthread_attr_setdetachstate(&attrs, PTHREAD_CREATE_DETACHED);
2392             errno = pthread_create(&the_thread, &attrs,
2393                (void*)serve, csp);
2394             child_id = errno ? -1 : 0;
2395             pthread_attr_destroy(&attrs);
2396          }
2397 #endif
2398
2399 #if defined(_WIN32) && !defined(_CYGWIN) && !defined(SELECTED_ONE_OPTION)
2400 #define SELECTED_ONE_OPTION
2401          child_id = _beginthread(
2402             (void (*)(void *))serve,
2403             64 * 1024,
2404             csp);
2405 #endif
2406
2407 #if defined(__OS2__) && !defined(SELECTED_ONE_OPTION)
2408 #define SELECTED_ONE_OPTION
2409          child_id = _beginthread(
2410             (void(* _Optlink)(void*))serve,
2411             NULL,
2412             64 * 1024,
2413             csp);
2414 #endif
2415
2416 #if defined(__BEOS__) && !defined(SELECTED_ONE_OPTION)
2417 #define SELECTED_ONE_OPTION
2418          {
2419             thread_id tid = spawn_thread
2420                (server_thread, "server", B_NORMAL_PRIORITY, csp);
2421
2422             if ((tid >= 0) && (resume_thread(tid) == B_OK))
2423             {
2424                child_id = (int) tid;
2425             }
2426             else
2427             {
2428                child_id = -1;
2429             }
2430          }
2431 #endif
2432
2433 #if defined(AMIGA) && !defined(SELECTED_ONE_OPTION)
2434 #define SELECTED_ONE_OPTION
2435          csp->cfd = ReleaseSocket(csp->cfd, -1);
2436          
2437          if((child_id = (int)CreateNewProcTags(
2438             NP_Entry, (ULONG)server_thread,
2439             NP_Output, Output(),
2440             NP_CloseOutput, FALSE,
2441             NP_Name, (ULONG)"privoxy child",
2442             NP_StackSize, 200*1024,
2443             TAG_DONE)))
2444          {
2445             childs++;
2446             ((struct Task *)child_id)->tc_UserData = csp;
2447             Signal((struct Task *)child_id, SIGF_SINGLE);
2448             Wait(SIGF_SINGLE);
2449          }
2450 #endif
2451
2452 #if !defined(SELECTED_ONE_OPTION)
2453          child_id = fork();
2454
2455          /* This block is only needed when using fork().
2456           * When using threads, the server thread was
2457           * created and run by the call to _beginthread().
2458           */
2459          if (child_id == 0)   /* child */
2460          {
2461             int rc = 0;
2462 #ifdef FEATURE_TOGGLE
2463             int inherited_toggle_state = global_toggle_state;
2464 #endif /* def FEATURE_TOGGLE */
2465
2466             serve(csp);
2467
2468             /* 
2469              * If we've been toggled or we've blocked the request, tell Mom
2470              */
2471
2472 #ifdef FEATURE_TOGGLE
2473             if (inherited_toggle_state != global_toggle_state)
2474             {
2475                rc |= RC_FLAG_TOGGLED;
2476             }
2477 #endif /* def FEATURE_TOGGLE */
2478
2479 #ifdef FEATURE_STATISTICS  
2480             if (csp->flags & CSP_FLAG_REJECTED)
2481             {
2482                rc |= RC_FLAG_BLOCKED;
2483             }
2484 #endif /* ndef FEATURE_STATISTICS */
2485
2486             _exit(rc);
2487          }
2488          else if (child_id > 0) /* parent */
2489          {
2490             /* in a fork()'d environment, the parent's
2491              * copy of the client socket and the CSP
2492              * are not used.
2493              */
2494             int child_status;
2495 #if !defined(_WIN32) && !defined(__CYGWIN__)
2496
2497             wait( &child_status );
2498
2499             /* 
2500              * Evaluate child's return code: If the child has
2501              *  - been toggled, toggle ourselves
2502              *  - blocked its request, bump up the stats counter
2503              */
2504
2505 #ifdef FEATURE_TOGGLE
2506             if (WIFEXITED(child_status) && (WEXITSTATUS(child_status) & RC_FLAG_TOGGLED))
2507             {
2508                global_toggle_state = !global_toggle_state;
2509             }
2510 #endif /* def FEATURE_TOGGLE */
2511
2512 #ifdef FEATURE_STATISTICS
2513             urls_read++;
2514             if (WIFEXITED(child_status) && (WEXITSTATUS(child_status) & RC_FLAG_BLOCKED))
2515             {
2516                urls_rejected++;
2517             }
2518 #endif /* def FEATURE_STATISTICS */ 
2519
2520 #endif /* !defined(_WIN32) && defined(__CYGWIN__) */
2521             close_socket(csp->cfd);
2522             csp->flags &= ~CSP_FLAG_ACTIVE;
2523          }
2524 #endif
2525
2526 #undef SELECTED_ONE_OPTION
2527 /* end of cpp switch () */
2528
2529          if (child_id < 0) /* failed */
2530          {
2531             char buf[BUFFER_SIZE];
2532
2533             log_error(LOG_LEVEL_ERROR, "can't fork: %E");
2534
2535             sprintf(buf , "Privoxy: can't fork: errno = %d", errno);
2536
2537             write_socket(csp->cfd, buf, strlen(buf));
2538             close_socket(csp->cfd);
2539             csp->flags &= ~CSP_FLAG_ACTIVE;
2540             sleep(5);
2541             continue;
2542          }
2543       }
2544       else
2545       {
2546          serve(csp);
2547       }
2548    }
2549
2550    /* NOTREACHED unless FEATURE_GRACEFUL_TERMINATION is defined */
2551
2552    /* Clean up.  Aim: free all memory (no leaks) */
2553 #ifdef FEATURE_GRACEFUL_TERMINATION
2554
2555    log_error(LOG_LEVEL_ERROR, "Graceful termination requested");
2556
2557    unload_current_config_file();
2558    unload_current_actions_file();
2559    unload_current_re_filterfile();
2560 #ifdef FEATURE_TRUST
2561    unload_current_trust_file();
2562 #endif
2563
2564    if (config->multi_threaded)
2565    {
2566       int i = 60;
2567       do
2568       {
2569          sleep(1);
2570          sweep();
2571       } while ((clients->next != NULL) && (--i > 0));
2572
2573       if (i <= 0)
2574       {
2575          log_error(LOG_LEVEL_ERROR, "Graceful termination failed - still some live clients after 1 minute wait.");
2576       }
2577    }
2578    sweep();
2579    sweep();
2580
2581 #if defined(unix)
2582    freez(basedir);
2583 #endif
2584    freez(configfile);
2585
2586 #ifdef FEATURE_COOKIE_JAR
2587    if (NULL != config->jar)
2588    {
2589       fclose(config->jar);
2590    }
2591 #endif
2592
2593 #if defined(_WIN32) && !defined(_WIN_CONSOLE)
2594    /* Cleanup - remove taskbar icon etc. */
2595    TermLogWindow();
2596 #endif
2597
2598    exit(0);
2599 #endif /* FEATURE_GRACEFUL_TERMINATION */
2600
2601 }
2602
2603
2604 /*
2605   Local Variables:
2606   tab-width: 3
2607   end:
2608 */