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