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