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