Fix some cparser warnings.
[privoxy.git] / errlog.c
1 const char errlog_rcs[] = "$Id: errlog.c,v 1.82 2008/11/23 16:06:58 fabiankeil Exp $";
2 /*********************************************************************
3  *
4  * File        :  $Source: /cvsroot/ijbswa/current/errlog.c,v $
5  *
6  * Purpose     :  Log errors to a designated destination in an elegant,
7  *                printf-like fashion.
8  *
9  * Copyright   :  Written by and Copyright (C) 2001-2008 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: errlog.c,v $
36  *    Revision 1.82  2008/11/23 16:06:58  fabiankeil
37  *    Update a log message I missed in 1.80.
38  *
39  *    Revision 1.81  2008/11/23 15:59:27  fabiankeil
40  *    - Update copyright range.
41  *    - Remove stray line breaks in a log message
42  *      nobody is supposed to see anyway.
43  *
44  *    Revision 1.80  2008/11/23 15:49:49  fabiankeil
45  *    In log_error(), don't surround the thread id with "Privoxy(" and ")".
46  *
47  *    Revision 1.79  2008/10/20 17:09:25  fabiankeil
48  *    Update init_error_log() description to match reality.
49  *
50  *    Revision 1.78  2008/09/07 16:59:31  fabiankeil
51  *    Update a comment to reflect that we
52  *    have mutex support on mingw32 now.
53  *
54  *    Revision 1.77  2008/09/07 12:43:44  fabiankeil
55  *    Move the LogPutString() call in log_error() into the locked
56  *    region so the Windows GUI log is consistent with the logfile.
57  *
58  *    Revision 1.76  2008/09/07 12:35:05  fabiankeil
59  *    Add mutex lock support for _WIN32.
60  *
61  *    Revision 1.75  2008/09/04 08:13:58  fabiankeil
62  *    Prepare for critical sections on Windows by adding a
63  *    layer of indirection before the pthread mutex functions.
64  *
65  *    Revision 1.74  2008/08/06 18:33:36  fabiankeil
66  *    If the "close fd first" workaround doesn't work,
67  *    the fatal error message will be lost, so we better
68  *    explain the consequences while we still can.
69  *
70  *    Revision 1.73  2008/08/04 19:06:55  fabiankeil
71  *    Add a lame workaround for the "can't open an already open
72  *    logfile on OS/2" problem reported by Maynard in #2028842
73  *    and describe what a real solution would look like.
74  *
75  *    Revision 1.72  2008/07/27 12:04:28  fabiankeil
76  *    Fix a comment typo.
77  *
78  *    Revision 1.71  2008/06/28 17:17:15  fabiankeil
79  *    Remove another stray semicolon.
80  *
81  *    Revision 1.70  2008/06/28 17:10:29  fabiankeil
82  *    Remove stray semicolon in get_log_timestamp().
83  *    Reported by Jochen Voss in #2005221.
84  *
85  *    Revision 1.69  2008/05/30 15:55:25  fabiankeil
86  *    Declare variable "debug" static and complain about its name.
87  *
88  *    Revision 1.68  2008/04/27 16:50:46  fabiankeil
89  *    Remove an incorrect assertion. The value of debug may change if
90  *    the configuration is reloaded in another thread. While we could
91  *    cache the initial value, the assertion doesn't seem worth it.
92  *
93  *    Revision 1.67  2008/03/27 18:27:23  fabiankeil
94  *    Remove kill-popups action.
95  *
96  *    Revision 1.66  2008/01/31 15:38:14  fabiankeil
97  *    - Make the logfp assertion more strict. As of 1.63, the "||" could
98  *      have been an "&&", which means we can use two separate assertions
99  *      and skip on of them on Windows.
100  *    - Break a long commit message line in two.
101  *
102  *    Revision 1.65  2008/01/31 14:44:33  fabiankeil
103  *    Use (a != b) instead of !(a == b) so the sanity check looks less insane.
104  *
105  *    Revision 1.64  2008/01/21 18:56:46  david__schmidt
106  *    Swap #def from negative to positive, re-joined it so it didn't
107  *    span an assertion (compilation failure on OS/2)
108  *
109  *    Revision 1.63  2007/12/15 19:49:32  fabiankeil
110  *    Stop overloading logfile to control the mingw32 log window as well.
111  *    It's no longer necessary now that we disable all debug lines by default
112  *    and at least one user perceived it as a regression (added in 1.55).
113  *
114  *    Revision 1.62  2007/11/30 15:33:46  fabiankeil
115  *    Unbreak LOG_LEVEL_FATAL. It wasn't fatal with logging disabled
116  *    and on mingw32 fatal log messages didn't end up in the log file.
117  *
118  *    Revision 1.61  2007/11/04 19:03:01  fabiankeil
119  *    Fix another deadlock Hal spotted and that mysteriously didn't affect FreeBSD.
120  *
121  *    Revision 1.60  2007/11/03 19:03:31  fabiankeil
122  *    - Prevent the Windows GUI from showing the version two times in a row.
123  *    - Stop using the imperative in the "(Re-)Open logfile" message.
124  *    - Ditch the "Switching to daemon mode" message as the detection
125  *      whether or not we're already in daemon mode doesn't actually work.
126  *
127  *    Revision 1.59  2007/11/01 12:50:56  fabiankeil
128  *    Here's looking at you, deadlock.
129  *
130  *    Revision 1.58  2007/10/28 19:04:21  fabiankeil
131  *    Don't mention daemon mode in "Logging disabled" message. Some
132  *    platforms call it differently and it's not really relevant anyway.
133  *
134  *    Revision 1.57  2007/10/27 13:02:26  fabiankeil
135  *    Relocate daemon-mode-related log messages to make sure
136  *    they aren't shown again in case of configuration reloads.
137  *
138  *    Revision 1.56  2007/10/14 14:26:56  fabiankeil
139  *    Remove the old log_error() version.
140  *
141  *    Revision 1.55  2007/10/14 14:12:41  fabiankeil
142  *    When in daemon mode, close stderr after the configuration file has been
143  *    parsed the first time. If logfile isn't set, stop logging. Fixes BR#897436.
144  *
145  *    Revision 1.54  2007/09/22 16:15:34  fabiankeil
146  *    - Let it compile with pcc.
147  *    - Move our includes below system includes to prevent macro conflicts.
148  *
149  *    Revision 1.53  2007/08/05 13:53:14  fabiankeil
150  *    #1763173 from Stefan Huehner: declare some more functions
151  *    static and use void instead of empty parameter lists.
152  *
153  *    Revision 1.52  2007/07/14 07:28:47  fabiankeil
154  *    Add translation function for JB_ERR_FOO codes.
155  *
156  *    Revision 1.51  2007/05/11 11:51:34  fabiankeil
157  *    Fix a type mismatch warning.
158  *
159  *    Revision 1.50  2007/04/11 10:55:44  fabiankeil
160  *    Enforce some assertions that could be triggered
161  *    on mingw32 and other systems where we use threads
162  *    but no locks.
163  *
164  *    Revision 1.49  2007/04/08 16:44:15  fabiankeil
165  *    We need <sys/time.h> for gettimeofday(), not <time.h>.
166  *
167  *    Revision 1.48  2007/03/31 13:33:28  fabiankeil
168  *    Add alternative log_error() with timestamps
169  *    that contain milliseconds and without using
170  *    strcpy(), strcat() or sprintf().
171  *
172  *    Revision 1.47  2006/11/28 15:25:15  fabiankeil
173  *    Only unlink the pidfile if it's actually used.
174  *
175  *    Revision 1.46  2006/11/13 19:05:51  fabiankeil
176  *    Make pthread mutex locking more generic. Instead of
177  *    checking for OSX and OpenBSD, check for FEATURE_PTHREAD
178  *    and use mutex locking unless there is an _r function
179  *    available. Better safe than sorry.
180  *
181  *    Fixes "./configure --disable-pthread" and should result
182  *    in less threading-related problems on pthread-using platforms,
183  *    but it still doesn't fix BR#1122404.
184  *
185  *    Revision 1.45  2006/08/21 11:15:54  david__schmidt
186  *    MS Visual C++ build updates
187  *
188  *    Revision 1.44  2006/08/18 16:03:16  david__schmidt
189  *    Tweak for OS/2 build happiness.
190  *
191  *    Revision 1.43  2006/08/03 02:46:41  david__schmidt
192  *    Incorporate Fabian Keil's patch work:
193  *    http://www.fabiankeil.de/sourcecode/privoxy/
194  *
195  *    Revision 1.42  2006/07/18 14:48:46  david__schmidt
196  *    Reorganizing the repository: swapping out what was HEAD (the old 3.1 branch)
197  *    with what was really the latest development (the v_3_0_branch branch)
198  *
199  *    Revision 1.40.2.4  2005/04/03 20:10:50  david__schmidt
200  *    Thanks to Jindrich Makovicka for a race condition fix for the log
201  *    file.  The race condition remains for non-pthread implementations.
202  *    Reference patch #1175720.
203  *
204  *    Revision 1.40.2.3  2003/03/07 03:41:04  david__schmidt
205  *    Wrapping all *_r functions (the non-_r versions of them) with mutex 
206  *    semaphores for OSX.  Hopefully this will take care of all of those pesky
207  *    crash reports.
208  *
209  *    Revision 1.40.2.2  2002/09/28 00:30:57  david__schmidt
210  *    Update error logging to give sane values for thread IDs on Mach kernels.
211  *    It's still a hack, but at least it looks farily normal.  We print the
212  *    absolute value of the first 4 bytes of the pthread_t modded with 1000.
213  *
214  *    Revision 1.40.2.1  2002/09/25 12:47:42  oes
215  *    Make log_error safe against NULL string arguments
216  *
217  *    Revision 1.40  2002/05/22 01:27:27  david__schmidt
218  *
219  *    Add os2_socket_strerr mirroring w32_socket_strerr.
220  *
221  *    Revision 1.39  2002/04/03 17:15:27  gliptak
222  *    zero padding thread ids in log
223  *
224  *    Revision 1.38  2002/03/31 17:18:59  jongfoster
225  *    Win32 only: Enabling STRICT to fix a VC++ compile warning.
226  *
227  *    Revision 1.37  2002/03/27 14:32:43  david__schmidt
228  *    More compiler warning message maintenance
229  *
230  *    Revision 1.36  2002/03/26 22:29:54  swa
231  *    we have a new homepage!
232  *
233  *    Revision 1.35  2002/03/24 15:23:33  jongfoster
234  *    Name changes
235  *
236  *    Revision 1.34  2002/03/24 13:25:43  swa
237  *    name change related issues
238  *
239  *    Revision 1.33  2002/03/13 00:27:04  jongfoster
240  *    Killing warnings
241  *
242  *    Revision 1.32  2002/03/07 03:46:17  oes
243  *    Fixed compiler warnings
244  *
245  *    Revision 1.31  2002/03/06 23:02:57  jongfoster
246  *    Removing tabs
247  *
248  *    Revision 1.30  2002/03/05 22:43:45  david__schmidt
249  *    - Better error reporting on OS/2
250  *    - Fix double-slash comment (oops)
251  *
252  *    Revision 1.29  2002/03/04 23:45:13  jongfoster
253  *    Printing thread ID if using Win32 native threads
254  *
255  *    Revision 1.28  2002/03/04 17:59:59  oes
256  *    Deleted deletePidFile(), cosmetics
257  *
258  *    Revision 1.27  2002/03/04 02:08:01  david__schmidt
259  *    Enable web editing of actions file on OS/2 (it had been broken all this time!)
260  *
261  *    Revision 1.26  2002/01/09 19:05:45  steudten
262  *    Fix big memory leak.
263  *
264  *    Revision 1.25  2002/01/09 14:32:08  oes
265  *    Added support for gmtime_r and localtime_r.
266  *
267  *    Revision 1.24  2001/12/30 14:07:32  steudten
268  *    - Add signal handling (unix)
269  *    - Add SIGHUP handler (unix)
270  *    - Add creation of pidfile (unix)
271  *    - Add action 'top' in rc file (RH)
272  *    - Add entry 'SIGNALS' to manpage
273  *    - Add exit message to logfile (unix)
274  *
275  *    Revision 1.23  2001/11/07 00:02:13  steudten
276  *    Add line number in error output for lineparsing for
277  *    actionsfile and configfile.
278  *    Special handling for CLF added.
279  *
280  *    Revision 1.22  2001/11/05 23:43:05  steudten
281  *    Add time+date to log files.
282  *
283  *    Revision 1.21  2001/10/25 03:40:47  david__schmidt
284  *    Change in porting tactics: OS/2's EMX porting layer doesn't allow multiple
285  *    threads to call select() simultaneously.  So, it's time to do a real, live,
286  *    native OS/2 port.  See defines for __EMX__ (the porting layer) vs. __OS2__
287  *    (native). Both versions will work, but using __OS2__ offers multi-threading.
288  *
289  *    Revision 1.20  2001/09/16 23:04:34  jongfoster
290  *    Fixing a warning
291  *
292  *    Revision 1.19  2001/09/13 20:08:06  jongfoster
293  *    Adding support for LOG_LEVEL_CGI
294  *
295  *    Revision 1.18  2001/09/10 11:27:24  oes
296  *    Declaration of w32_socket_strerr now conditional
297  *
298  *    Revision 1.17  2001/09/10 10:17:13  oes
299  *    Removed unused variable; Fixed sprintf format
300  *
301  *    Revision 1.16  2001/07/30 22:08:36  jongfoster
302  *    Tidying up #defines:
303  *    - All feature #defines are now of the form FEATURE_xxx
304  *    - Permanently turned off WIN_GUI_EDIT
305  *    - Permanently turned on WEBDAV and SPLIT_PROXY_ARGS
306  *
307  *    Revision 1.15  2001/07/29 17:41:10  jongfoster
308  *    Now prints thread ID for each message (pthreads only)
309  *
310  *    Revision 1.14  2001/07/19 19:03:48  haroon
311  *    - Added case for LOG_LEVEL_POPUPS
312  *
313  *    Revision 1.13  2001/07/13 13:58:58  oes
314  *     - Added case for LOG_LEVEL_DEANIMATE
315  *     - Removed all #ifdef PCRS
316  *
317  *    Revision 1.12  2001/06/09 10:55:28  jongfoster
318  *    Changing BUFSIZ ==> BUFFER_SIZE
319  *
320  *    Revision 1.11  2001/06/01 18:14:49  jongfoster
321  *    Changing the calls to strerr() to check HAVE_STRERR (which is defined
322  *    in config.h if appropriate) rather than the NO_STRERR macro.
323  *
324  *    Revision 1.10  2001/05/29 11:52:21  oes
325  *    Conditional compilation of w32_socket_error
326  *
327  *    Revision 1.9  2001/05/28 16:15:17  jongfoster
328  *    Improved reporting of errors under Win32.
329  *
330  *    Revision 1.8  2001/05/26 17:25:14  jongfoster
331  *    Added support for CLF (Common Log Format) and fixed LOG_LEVEL_LOG
332  *
333  *    Revision 1.7  2001/05/26 15:21:28  jongfoster
334  *    Activity animation in Win32 GUI now works even if debug==0
335  *
336  *    Revision 1.6  2001/05/25 21:55:08  jongfoster
337  *    Now cleans up properly on FATAL (removes taskbar icon etc)
338  *
339  *    Revision 1.5  2001/05/22 18:46:04  oes
340  *
341  *    - Enabled filtering banners by size rather than URL
342  *      by adding patterns that replace all standard banner
343  *      sizes with the "Junkbuster" gif to the re_filterfile
344  *
345  *    - Enabled filtering WebBugs by providing a pattern
346  *      which kills all 1x1 images
347  *
348  *    - Added support for PCRE_UNGREEDY behaviour to pcrs,
349  *      which is selected by the (nonstandard and therefore
350  *      capital) letter 'U' in the option string.
351  *      It causes the quantifiers to be ungreedy by default.
352  *      Appending a ? turns back to greedy (!).
353  *
354  *    - Added a new interceptor ijb-send-banner, which
355  *      sends back the "Junkbuster" gif. Without imagelist or
356  *      MSIE detection support, or if tinygif = 1, or the
357  *      URL isn't recognized as an imageurl, a lame HTML
358  *      explanation is sent instead.
359  *
360  *    - Added new feature, which permits blocking remote
361  *      script redirects and firing back a local redirect
362  *      to the browser.
363  *      The feature is conditionally compiled, i.e. it
364  *      can be disabled with --disable-fast-redirects,
365  *      plus it must be activated by a "fast-redirects"
366  *      line in the config file, has its own log level
367  *      and of course wants to be displayed by show-proxy-args
368  *      Note: Boy, all the #ifdefs in 1001 locations and
369  *      all the fumbling with configure.in and acconfig.h
370  *      were *way* more work than the feature itself :-(
371  *
372  *    - Because a generic redirect template was needed for
373  *      this, tinygif = 3 now uses the same.
374  *
375  *    - Moved GIFs, and other static HTTP response templates
376  *      to project.h
377  *
378  *    - Some minor fixes
379  *
380  *    - Removed some >400 CRs again (Jon, you really worked
381  *      a lot! ;-)
382  *
383  *    Revision 1.4  2001/05/21 19:32:54  jongfoster
384  *    Added another #ifdef _WIN_CONSOLE
385  *
386  *    Revision 1.3  2001/05/20 01:11:40  jongfoster
387  *    Added support for LOG_LEVEL_FATAL
388  *    Renamed LOG_LEVEL_FRC to LOG_LEVEL_FORCE,
389  *    and LOG_LEVEL_REF to LOG_LEVEL_RE_FILTER
390  *
391  *    Revision 1.2  2001/05/17 22:42:01  oes
392  *     - Cleaned CRLF's from the sources and related files
393  *     - Repaired logging for REF and FRC
394  *
395  *    Revision 1.1.1.1  2001/05/15 13:58:51  oes
396  *    Initial import of version 2.9.3 source tree
397  *
398  *
399  *********************************************************************/
400 \f
401
402 #include <stdlib.h>
403 #include <stdio.h>
404 #include <stdarg.h>
405 #include <string.h>
406
407 #include "config.h"
408 #include "miscutil.h"
409
410 /* For gettimeofday() */
411 #include <sys/time.h>
412
413 #if !defined(_WIN32) && !defined(__OS2__)
414 #include <unistd.h>
415 #endif /* !defined(_WIN32) && !defined(__OS2__) */
416
417 #include <errno.h>
418 #include <assert.h>
419
420 #ifdef _WIN32
421 #ifndef STRICT
422 #define STRICT
423 #endif
424 #include <windows.h>
425 #ifndef _WIN_CONSOLE
426 #include "w32log.h"
427 #endif /* ndef _WIN_CONSOLE */
428 #endif /* def _WIN32 */
429 #ifdef _MSC_VER
430 #define inline __inline
431 #endif /* def _MSC_VER */
432
433 #ifdef __OS2__
434 #include <sys/socket.h> /* For sock_errno */
435 #define INCL_DOS
436 #include <os2.h>
437 #endif
438
439 #include "errlog.h"
440 #include "project.h"
441 #include "jcc.h"
442
443 const char errlog_h_rcs[] = ERRLOG_H_VERSION;
444
445
446 /*
447  * LOG_LEVEL_FATAL cannot be turned off.  (There are
448  * some exceptional situations where we need to get a
449  * message to the user).
450  */
451 #define LOG_LEVEL_MINIMUM  LOG_LEVEL_FATAL
452
453 /* where to log (default: stderr) */
454 static FILE *logfp = NULL;
455
456 /* logging detail level. XXX: stupid name. */
457 static int debug = (LOG_LEVEL_FATAL | LOG_LEVEL_ERROR | LOG_LEVEL_INFO);  
458
459 /* static functions */
460 static void fatal_error(const char * error_message);
461 #ifdef _WIN32
462 static char *w32_socket_strerr(int errcode, char *tmp_buf);
463 #endif
464 #ifdef __OS2__
465 static char *os2_socket_strerr(int errcode, char *tmp_buf);
466 #endif
467
468 #ifdef MUTEX_LOCKS_AVAILABLE
469 static inline void lock_logfile(void)
470 {
471    privoxy_mutex_lock(&log_mutex);
472 }
473 static inline void unlock_logfile(void)
474 {
475    privoxy_mutex_unlock(&log_mutex);
476 }
477 static inline void lock_loginit(void)
478 {
479    privoxy_mutex_lock(&log_init_mutex);
480 }
481 static inline void unlock_loginit(void)
482 {
483    privoxy_mutex_unlock(&log_init_mutex);
484 }
485 #else /* ! MUTEX_LOCKS_AVAILABLE */
486 /*
487  * FIXME we need a cross-platform locking mechanism.
488  * The locking/unlocking functions below should be 
489  * fleshed out for non-pthread implementations.
490  */ 
491 static inline void lock_logfile() {}
492 static inline void unlock_logfile() {}
493 static inline void lock_loginit() {}
494 static inline void unlock_loginit() {}
495 #endif
496
497 /*********************************************************************
498  *
499  * Function    :  fatal_error
500  *
501  * Description :  Displays a fatal error to standard error (or, on 
502  *                a WIN32 GUI, to a dialog box), and exits
503  *                JunkBuster with status code 1.
504  *
505  * Parameters  :
506  *          1  :  error_message = The error message to display.
507  *
508  * Returns     :  Does not return.
509  *
510  *********************************************************************/
511 static void fatal_error(const char * error_message)
512 {
513 #if defined(_WIN32) && !defined(_WIN_CONSOLE)
514    MessageBox(g_hwndLogFrame, error_message, "Privoxy Error", 
515       MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_SETFOREGROUND | MB_TOPMOST);  
516
517    /* Cleanup - remove taskbar icon etc. */
518    TermLogWindow();
519 #endif /* defined(_WIN32) && !defined(_WIN_CONSOLE) */
520
521    if (logfp != NULL)
522    {
523       fputs(error_message, logfp);
524    }
525
526 #if defined(unix)
527    if (pidfile)
528    {
529       unlink(pidfile);
530    }
531 #endif /* unix */
532
533    exit(1);
534 }
535
536
537 /*********************************************************************
538  *
539  * Function    :  show_version
540  *
541  * Description :  Logs the Privoxy version and the program name.
542  *
543  * Parameters  :
544  *          1  :  prog_name = The program name.
545  *
546  * Returns     :  Nothing.
547  *
548  *********************************************************************/
549 static void show_version(const char *prog_name)
550 {
551    log_error(LOG_LEVEL_INFO, "Privoxy version " VERSION);
552    if (prog_name != NULL)
553    {
554       log_error(LOG_LEVEL_INFO, "Program name: %s", prog_name);
555    }
556 }
557
558
559 /*********************************************************************
560  *
561  * Function    :  init_log_module
562  *
563  * Description :  Initializes the logging module to log to stderr.
564  *                Can only be called while stderr hasn't been closed
565  *                yet and is only supposed to be called once.
566  *
567  * Parameters  :
568  *          1  :  prog_name = The program name.
569  *
570  * Returns     :  Nothing.
571  *
572  *********************************************************************/
573 void init_log_module(const char *prog_name)
574 {
575    lock_logfile();
576    logfp = stderr;
577    unlock_logfile();
578    set_debug_level(debug);
579    show_version(prog_name);
580 }
581
582
583 /*********************************************************************
584  *
585  * Function    :  set_debug_level
586  *
587  * Description :  Sets the debug level to the provided value
588  *                plus LOG_LEVEL_MINIMUM.
589  *
590  *                XXX: we should only use the LOG_LEVEL_MINIMUM
591  *                until the first time the configuration file has
592  *                been parsed.
593  *                
594  * Parameters  :  1: debug_level = The debug level to set.
595  *
596  * Returns     :  Nothing.
597  *
598  *********************************************************************/
599 void set_debug_level(int debug_level)
600 {
601    debug = debug_level | LOG_LEVEL_MINIMUM;
602 }
603
604
605 /*********************************************************************
606  *
607  * Function    :  disable_logging
608  *
609  * Description :  Disables logging.
610  *                
611  * Parameters  :  None.
612  *
613  * Returns     :  Nothing.
614  *
615  *********************************************************************/
616 void disable_logging(void)
617 {
618    if (logfp != NULL)
619    {
620       log_error(LOG_LEVEL_INFO,
621          "No logfile configured. Please enable it before reporting any problems.");
622       lock_logfile();
623       fclose(logfp);
624       logfp = NULL;
625       unlock_logfile();
626    }
627 }
628
629
630 /*********************************************************************
631  *
632  * Function    :  init_error_log
633  *
634  * Description :  Initializes the logging module to log to a file.
635  *
636  *                XXX: should be renamed.
637  *
638  * Parameters  :
639  *          1  :  prog_name  = The program name.
640  *          2  :  logfname   = The logfile to (re)open.
641  *
642  * Returns     :  N/A
643  *
644  *********************************************************************/
645 void init_error_log(const char *prog_name, const char *logfname)
646 {
647    FILE *fp;
648
649    assert(NULL != logfname);
650
651    lock_loginit();
652
653    if (logfp != NULL)
654    {
655       log_error(LOG_LEVEL_INFO, "(Re-)Opening logfile \'%s\'", logfname);
656    }
657
658    /* set the designated log file */
659    fp = fopen(logfname, "a");
660    if ((NULL == fp) && (logfp != NULL))
661    {
662       /*
663        * Some platforms (like OS/2) don't allow us to open
664        * the same file twice, therefore we give it another
665        * shot after closing the old file descriptor first.
666        *
667        * We don't do it right away because it prevents us
668        * from logging the "can't open logfile" message to
669        * the old logfile.
670        *
671        * XXX: this is a lame workaround and once the next
672        * release is out we should stop bothering reopening
673        * the logfile unless we have to.
674        *
675        * Currently we reopen it every time the config file
676        * has been reloaded, but actually we only have to
677        * reopen it if the file name changed or if the
678        * configuration reloas was caused by a SIGHUP.
679        */
680       log_error(LOG_LEVEL_INFO, "Failed to reopen logfile: \'%s\'. "
681          "Retrying after closing the old file descriptor first. If that "
682          "doesn't work, Privoxy will exit without being able to log a message.",
683          logfname);
684       lock_logfile();
685       fclose(logfp);
686       logfp = NULL;
687       unlock_logfile();
688       fp = fopen(logfname, "a");
689    }
690
691    if (NULL == fp)
692    {
693       log_error(LOG_LEVEL_FATAL, "init_error_log(): can't open logfile: \'%s\'", logfname);
694    }
695
696    /* set logging to be completely unbuffered */
697    setbuf(fp, NULL);
698
699    lock_logfile();
700    if (logfp != NULL)
701    {
702       fclose(logfp);
703    }
704    logfp = fp;
705    unlock_logfile();
706
707 #if !defined(_WIN32)
708    /*
709     * Prevent the Windows GUI from showing the version two
710     * times in a row on startup. It already displayed the show_version()
711     * call from init_log_module() that other systems write to stderr.
712     *
713     * This means mingw32 users will never see the version in their
714     * log file, but I assume they wouldn't look for it there anyway
715     * and simply use the "Help/About Privoxy" menu.
716     */
717    show_version(prog_name);
718 #endif /* def unix */
719
720    unlock_loginit();
721
722 } /* init_error_log */
723
724
725 /*********************************************************************
726  *
727  * Function    :  get_thread_id
728  *
729  * Description :  Returns a number that is different for each thread.
730  *
731  *                XXX: Should be moved elsewhere (miscutil.c?)
732  *                
733  * Parameters  :  None
734  *
735  * Returns     :  thread_id
736  *
737  *********************************************************************/
738 static long get_thread_id(void)
739 {
740    long this_thread = 1;  /* was: pthread_t this_thread;*/
741
742 #ifdef __OS2__
743    PTIB     ptib;
744    APIRET   ulrc; /* XXX: I have no clue what this does */
745 #endif /* __OS2__ */
746
747    /* FIXME get current thread id */
748 #ifdef FEATURE_PTHREAD
749    this_thread = (long)pthread_self();
750 #ifdef __MACH__
751    /*
752     * Mac OSX (and perhaps other Mach instances) doesn't have a debuggable
753     * value at the first 4 bytes of pthread_self()'s return value, a pthread_t.
754     * pthread_t is supposed to be opaque... but it's fairly random, though, so
755     * we make it mostly presentable.
756     */
757    this_thread = abs(this_thread % 1000);
758 #endif /* def __MACH__ */
759 #elif defined(_WIN32)
760    this_thread = GetCurrentThreadId();
761 #elif defined(__OS2__)
762    ulrc = DosGetInfoBlocks(&ptib, NULL);
763    if (ulrc == 0)
764      this_thread = ptib -> tib_ptib2 -> tib2_ultid;
765 #endif /* def FEATURE_PTHREAD */
766
767    return this_thread;
768 }
769
770
771 /*********************************************************************
772  *
773  * Function    :  get_log_timestamp
774  *
775  * Description :  Generates the time stamp for the log message prefix.
776  *
777  * Parameters  :
778  *          1  :  buffer = Storage buffer
779  *          2  :  buffer_size = Size of storage buffer
780  *
781  * Returns     :  Number of written characters or 0 for error.
782  *
783  *********************************************************************/
784 static inline size_t get_log_timestamp(char *buffer, size_t buffer_size)
785 {
786    size_t length;
787    time_t now; 
788    struct tm tm_now;
789    struct timeval tv_now; /* XXX: stupid name */
790    long msecs;
791    int msecs_length = 0;
792
793    gettimeofday(&tv_now, NULL);
794    msecs = tv_now.tv_usec / 1000;
795
796    time(&now);
797
798 #ifdef HAVE_LOCALTIME_R
799    tm_now = *localtime_r(&now, &tm_now);
800 #elif FEATURE_PTHREAD
801    privoxy_mutex_lock(&localtime_mutex);
802    tm_now = *localtime(&now); 
803    privoxy_mutex_unlock(&localtime_mutex);
804 #else
805    tm_now = *localtime(&now); 
806 #endif
807
808    length = strftime(buffer, buffer_size, "%b %d %H:%M:%S", &tm_now);
809    if (length > (size_t)0)
810    {
811       msecs_length = snprintf(buffer+length, buffer_size - length, ".%.3ld", msecs);               
812    }
813    if (msecs_length > 0)
814    {
815       length += (size_t)msecs_length;
816    }
817    else
818    {
819       length = 0;
820    }
821
822    return length;
823 }
824
825
826 /*********************************************************************
827  *
828  * Function    :  get_clf_timestamp
829  *
830  * Description :  Generates a Common Log Format time string.
831  *
832  * Parameters  :
833  *          1  :  buffer = Storage buffer
834  *          2  :  buffer_size = Size of storage buffer
835  *
836  * Returns     :  Number of written characters or 0 for error.
837  *
838  *********************************************************************/
839 static inline size_t get_clf_timestamp(char *buffer, size_t buffer_size)
840 {
841    /*
842     * Complex because not all OSs have tm_gmtoff or
843     * the %z field in strftime()
844     */
845    time_t now;
846    struct tm *tm_now; 
847    struct tm gmt;
848 #ifdef HAVE_LOCALTIME_R
849    struct tm dummy;
850 #endif
851    int days, hrs, mins;
852    size_t length;
853    int tz_length = 0;
854
855    time (&now); 
856 #ifdef HAVE_GMTIME_R
857    gmt = *gmtime_r(&now, &gmt);
858 #elif FEATURE_PTHREAD
859    privoxy_mutex_lock(&gmtime_mutex);
860    gmt = *gmtime(&now);
861    privoxy_mutex_unlock(&gmtime_mutex);
862 #else
863    gmt = *gmtime(&now);
864 #endif
865 #ifdef HAVE_LOCALTIME_R
866    tm_now = localtime_r(&now, &dummy);
867 #elif FEATURE_PTHREAD
868    privoxy_mutex_lock(&localtime_mutex);
869    tm_now = localtime(&now); 
870    privoxy_mutex_unlock(&localtime_mutex);
871 #else
872    tm_now = localtime(&now); 
873 #endif
874    days = tm_now->tm_yday - gmt.tm_yday; 
875    hrs = ((days < -1 ? 24 : 1 < days ? -24 : days * 24) + tm_now->tm_hour - gmt.tm_hour); 
876    mins = hrs * 60 + tm_now->tm_min - gmt.tm_min; 
877
878    length = strftime(buffer, buffer_size, "%d/%b/%Y:%H:%M:%S ", tm_now);
879
880    if (length > (size_t)0)
881    {
882       tz_length = snprintf(buffer+length, buffer_size-length,
883                      "%+03d%02d", mins / 60, abs(mins) % 60);
884    }
885    if (tz_length > 0)
886    {
887       length += (size_t)tz_length;
888    }
889    else
890    {
891       length = 0;
892    }
893
894    return length;
895 }
896
897
898 /*********************************************************************
899  *
900  * Function    :  get_log_level_string
901  *
902  * Description :  Translates a numerical loglevel into a string.
903  *
904  * Parameters  :  
905  *          1  :  loglevel = LOG_LEVEL_FOO
906  *
907  * Returns     :  Log level string.
908  *
909  *********************************************************************/
910 static inline const char *get_log_level_string(int loglevel)
911 {
912    char *log_level_string = NULL;
913
914    assert(0 < loglevel);
915
916    switch (loglevel)
917    {
918       case LOG_LEVEL_ERROR:
919          log_level_string = "Error";
920          break;
921       case LOG_LEVEL_FATAL:
922          log_level_string = "Fatal error";
923          break;
924       case LOG_LEVEL_GPC:
925          log_level_string = "Request";
926          break;
927       case LOG_LEVEL_CONNECT:
928          log_level_string = "Connect";
929          break;
930       case LOG_LEVEL_LOG:
931          log_level_string = "Writing";
932          break;
933       case LOG_LEVEL_HEADER:
934          log_level_string = "Header";
935          break;
936       case LOG_LEVEL_INFO:
937          log_level_string = "Info";
938          break;
939       case LOG_LEVEL_RE_FILTER:
940          log_level_string = "Re-Filter";
941          break;
942 #ifdef FEATURE_FORCE_LOAD
943       case LOG_LEVEL_FORCE:
944          log_level_string = "Force";
945          break;
946 #endif /* def FEATURE_FORCE_LOAD */
947 #ifdef FEATURE_FAST_REDIRECTS
948       case LOG_LEVEL_REDIRECTS:
949          log_level_string = "Redirect";
950          break;
951 #endif /* def FEATURE_FAST_REDIRECTS */
952       case LOG_LEVEL_DEANIMATE:
953          log_level_string = "Gif-Deanimate";
954          break;
955       case LOG_LEVEL_CGI:
956          log_level_string = "CGI";
957          break;
958       default:
959          log_level_string = "Unknown log level";
960          break;
961    }
962    assert(NULL != log_level_string);
963
964    return log_level_string;
965 }
966
967
968 /*********************************************************************
969  *
970  * Function    :  log_error
971  *
972  * Description :  This is the error-reporting and logging function.
973  *
974  * Parameters  :
975  *          1  :  loglevel  = the type of message to be logged
976  *          2  :  fmt       = the main string we want logged, printf-like
977  *          3  :  ...       = arguments to be inserted in fmt (printf-like).
978  *
979  * Returns     :  N/A
980  *
981  *********************************************************************/
982 void log_error(int loglevel, const char *fmt, ...)
983 {
984    va_list ap;
985    char *outbuf = NULL;
986    static char *outbuf_save = NULL;
987    char tempbuf[BUFFER_SIZE];
988    size_t length = 0;
989    const char * src = fmt;
990    long thread_id;
991    char timestamp[30];
992    /*
993     * XXX: Make this a config option,
994     * why else do we allocate instead of using
995     * an array?
996     */
997    size_t log_buffer_size = BUFFER_SIZE;
998
999 #if defined(_WIN32) && !defined(_WIN_CONSOLE)
1000    /*
1001     * Irrespective of debug setting, a GET/POST/CONNECT makes
1002     * the taskbar icon animate.  (There is an option to disable
1003     * this but checking that is handled inside LogShowActivity()).
1004     */
1005    if (loglevel == LOG_LEVEL_GPC)
1006    {
1007       LogShowActivity();
1008    }
1009 #endif /* defined(_WIN32) && !defined(_WIN_CONSOLE) */
1010
1011    /*
1012     * verify that the loglevel applies to current
1013     * settings and that logging is enabled.
1014     * Bail out otherwise.
1015     */
1016    if ((0 == (loglevel & debug))
1017 #ifndef _WIN32
1018       || (logfp == NULL)
1019 #endif
1020       )
1021    {
1022       return;
1023    }
1024
1025    thread_id = get_thread_id();
1026    get_log_timestamp(timestamp, sizeof(timestamp));
1027
1028    /* protect the whole function because of the static buffer (outbuf) */
1029    lock_logfile();
1030
1031    if (NULL == outbuf_save) 
1032    {
1033       outbuf_save = (char*)zalloc(log_buffer_size + 1); /* +1 for paranoia */
1034       if (NULL == outbuf_save)
1035       {
1036          snprintf(tempbuf, sizeof(tempbuf),
1037             "%s %08lx Fatal error: Out of memory in log_error().",
1038             timestamp, thread_id);
1039          fatal_error(tempbuf); /* Exit */
1040       }
1041    }
1042    outbuf = outbuf_save;
1043
1044    /*
1045     * Memsetting the whole buffer to zero (in theory)
1046     * makes things easier later on.
1047     */
1048    memset(outbuf, 0, log_buffer_size);
1049
1050    /* Add prefix for everything but Common Log Format messages */
1051    if (loglevel != LOG_LEVEL_CLF)
1052    {
1053       length = (size_t)snprintf(outbuf, log_buffer_size, "%s %08lx %s: ",
1054          timestamp, thread_id, get_log_level_string(loglevel));
1055    }
1056
1057    /* get ready to scan var. args. */
1058    va_start(ap, fmt);
1059
1060    /* build formatted message from fmt and var-args */
1061    while ((*src) && (length < log_buffer_size-2))
1062    {
1063       const char *sval = NULL; /* %N string  */
1064       int ival;                /* %N string length or an error code */
1065       unsigned uval;           /* %u value */
1066       long lval;               /* %l value */
1067       unsigned long ulval;     /* %ul value */
1068       char ch;
1069       const char *format_string = tempbuf;
1070
1071       ch = *src++;
1072       if (ch != '%')
1073       {
1074          outbuf[length++] = ch;
1075          /*
1076           * XXX: Only necessary on platforms where multiple threads
1077           * can write to the buffer at the same time because we
1078           * don't support mutexes (OS/2 for example).
1079           */
1080          outbuf[length] = '\0';
1081          continue;
1082       }
1083       outbuf[length] = '\0';
1084       ch = *src++;
1085       switch (ch) {
1086          case '%':
1087             tempbuf[0] = '%';
1088             tempbuf[1] = '\0';
1089             break;
1090          case 'd':
1091             ival = va_arg( ap, int );
1092             snprintf(tempbuf, sizeof(tempbuf), "%d", ival);
1093             break;
1094          case 'u':
1095             uval = va_arg( ap, unsigned );
1096             snprintf(tempbuf, sizeof(tempbuf), "%u", uval);
1097             break;
1098          case 'l':
1099             /* this is a modifier that must be followed by u or d */
1100             ch = *src++;
1101             if (ch == 'd')
1102             {
1103                lval = va_arg( ap, long );
1104                snprintf(tempbuf, sizeof(tempbuf), "%ld", lval);
1105             }
1106             else if (ch == 'u')
1107             {
1108                ulval = va_arg( ap, unsigned long );
1109                snprintf(tempbuf, sizeof(tempbuf), "%lu", ulval);
1110             }
1111             else
1112             {
1113                snprintf(tempbuf, sizeof(tempbuf), "Bad format string: \"%s\"", fmt);
1114                loglevel = LOG_LEVEL_FATAL;
1115             }
1116             break;
1117          case 'c':
1118             /*
1119              * Note that char paramaters are converted to int, so we need to
1120              * pass "int" to va_arg.  (See K&R, 2nd ed, section A7.3.2, page 202)
1121              */
1122             tempbuf[0] = (char) va_arg(ap, int);
1123             tempbuf[1] = '\0';
1124             break;
1125          case 's':
1126             format_string = va_arg(ap, char *);
1127             if (format_string == NULL)
1128             {
1129                format_string = "[null]";
1130             }
1131             break;
1132          case 'N':
1133             /*
1134              * Non-standard: Print a counted unterminated string.
1135              * Takes 2 parameters: int length, const char * string.
1136              */
1137             ival = va_arg(ap, int);
1138             sval = va_arg(ap, char *);
1139             if (sval == NULL)
1140             {
1141                format_string = "[null]";
1142             }
1143             else if (ival <= 0)
1144             {
1145                if (0 == ival)
1146                {
1147                   /* That's ok (but stupid) */
1148                   tempbuf[0] = '\0';
1149                }
1150                else
1151                {
1152                   /*
1153                    * That's not ok (and even more stupid)
1154                    */
1155                   assert(ival >= 0);
1156                   format_string = "[counted string lenght < 0]";
1157                }
1158             }
1159             else if ((size_t)ival >= sizeof(tempbuf))
1160             {
1161                /*
1162                 * String is too long, copy as much as possible.
1163                 * It will be further truncated later.
1164                 */
1165                memcpy(tempbuf, sval, sizeof(tempbuf)-1);
1166                tempbuf[sizeof(tempbuf)-1] = '\0';
1167             }
1168             else
1169             {
1170                memcpy(tempbuf, sval, (size_t) ival);
1171                tempbuf[ival] = '\0';
1172             }
1173             break;
1174          case 'E':
1175             /* Non-standard: Print error code from errno */
1176 #ifdef _WIN32
1177             ival = WSAGetLastError();
1178             format_string = w32_socket_strerr(ival, tempbuf);
1179 #elif __OS2__
1180             ival = sock_errno();
1181             if (ival != 0)
1182             {
1183                format_string = os2_socket_strerr(ival, tempbuf);
1184             }
1185             else
1186             {
1187                ival = errno;
1188                format_string = strerror(ival);
1189             }
1190 #else /* ifndef _WIN32 */
1191             ival = errno; 
1192 #ifdef HAVE_STRERROR
1193             format_string = strerror(ival);
1194 #else /* ifndef HAVE_STRERROR */
1195             format_string = NULL;
1196 #endif /* ndef HAVE_STRERROR */
1197             if (sval == NULL)
1198             {
1199                snprintf(tempbuf, sizeof(tempbuf), "(errno = %d)", ival);
1200             }
1201 #endif /* ndef _WIN32 */
1202             break;
1203          case 'T':
1204             /* Non-standard: Print a Common Log File timestamp */
1205             get_clf_timestamp(tempbuf, sizeof(tempbuf));
1206             break;
1207          default:
1208             snprintf(tempbuf, sizeof(tempbuf), "Bad format string: \"%s\"", fmt);
1209             loglevel = LOG_LEVEL_FATAL;
1210             break;
1211       } /* switch( p ) */
1212
1213       assert(length < log_buffer_size);
1214       length += strlcpy(outbuf + length, format_string, log_buffer_size - length);
1215
1216       if (length >= log_buffer_size-2)
1217       {
1218          static char warning[] = "... [too long, truncated]";
1219
1220          length = log_buffer_size - sizeof(warning) - 1;
1221          length += strlcpy(outbuf + length, warning, log_buffer_size - length);
1222          assert(length < log_buffer_size);
1223
1224          break;
1225       }
1226    } /* for( p ... ) */
1227
1228    /* done with var. args */
1229    va_end(ap);
1230
1231    assert(length < log_buffer_size);
1232    length += strlcpy(outbuf + length, "\n", log_buffer_size - length);
1233
1234    /* Some sanity checks */
1235    if ((length >= log_buffer_size)
1236     || (outbuf[log_buffer_size-1] != '\0')
1237     || (outbuf[log_buffer_size] != '\0')
1238       )
1239    {
1240       /* Repeat as assertions */
1241       assert(length < log_buffer_size);
1242       assert(outbuf[log_buffer_size-1] == '\0');
1243       /*
1244        * outbuf's real size is log_buffer_size+1,
1245        * so while this looks like an off-by-one,
1246        * we're only checking our paranoia byte.
1247        */
1248       assert(outbuf[log_buffer_size] == '\0');
1249
1250       snprintf(outbuf, log_buffer_size,
1251          "%s %08lx Fatal error: log_error()'s sanity checks failed."
1252          "length: %d. Exiting.",
1253          timestamp, thread_id, (int)length);
1254       loglevel = LOG_LEVEL_FATAL;
1255    }
1256
1257 #ifndef _WIN32
1258    /*
1259     * On Windows this is acceptable in case
1260     * we are logging to the GUI window only.
1261     */
1262    assert(NULL != logfp);
1263 #endif
1264
1265    if (loglevel == LOG_LEVEL_FATAL)
1266    {
1267       fatal_error(outbuf_save);
1268       /* Never get here */
1269    }
1270    if (logfp != NULL)
1271    {
1272       fputs(outbuf_save, logfp);
1273    }
1274
1275 #if defined(_WIN32) && !defined(_WIN_CONSOLE)
1276    /* Write to display */
1277    LogPutString(outbuf_save);
1278 #endif /* defined(_WIN32) && !defined(_WIN_CONSOLE) */
1279
1280    unlock_logfile();
1281
1282 }
1283
1284
1285 /*********************************************************************
1286  *
1287  * Function    :  jb_err_to_string
1288  *
1289  * Description :  Translates JB_ERR_FOO codes into strings.
1290  *
1291  *                XXX: the type of error codes is jb_err
1292  *                but the typedef'inition is currently not
1293  *                visible to all files that include errlog.h.
1294  *
1295  * Parameters  :
1296  *          1  :  error = a valid jb_err code
1297  *
1298  * Returns     :  A string with the jb_err translation
1299  *
1300  *********************************************************************/
1301 const char *jb_err_to_string(int error)
1302 {
1303    switch (error)
1304    {
1305       case JB_ERR_OK:
1306          return "Success, no error";
1307       case JB_ERR_MEMORY:
1308          return "Out of memory";
1309       case JB_ERR_CGI_PARAMS:
1310          return "Missing or corrupt CGI parameters";
1311       case JB_ERR_FILE:
1312          return "Error opening, reading or writing a file";
1313       case JB_ERR_PARSE:
1314          return "Parse error";
1315       case JB_ERR_MODIFIED:
1316          return "File has been modified outside of the CGI actions editor.";
1317       case JB_ERR_COMPRESS:
1318          return "(De)compression failure";
1319       default:
1320          assert(0);
1321          return "Unknown error";
1322    }
1323    assert(0);
1324    return "Internal error";
1325 }
1326
1327 #ifdef _WIN32
1328 /*********************************************************************
1329  *
1330  * Function    :  w32_socket_strerr
1331  *
1332  * Description :  Translate the return value from WSAGetLastError()
1333  *                into a string.
1334  *
1335  * Parameters  :
1336  *          1  :  errcode = The return value from WSAGetLastError().
1337  *          2  :  tmp_buf = A temporary buffer that might be used to
1338  *                          store the string.
1339  *
1340  * Returns     :  String representing the error code.  This may be
1341  *                a global string constant or a string stored in
1342  *                tmp_buf.
1343  *
1344  *********************************************************************/
1345 static char *w32_socket_strerr(int errcode, char *tmp_buf)
1346 {
1347 #define TEXT_FOR_ERROR(code,text) \
1348    if (errcode == code)           \
1349    {                              \
1350       return #code " - " text;    \
1351    }
1352
1353    TEXT_FOR_ERROR(WSAEACCES, "Permission denied")
1354    TEXT_FOR_ERROR(WSAEADDRINUSE, "Address already in use.")
1355    TEXT_FOR_ERROR(WSAEADDRNOTAVAIL, "Cannot assign requested address.");
1356    TEXT_FOR_ERROR(WSAEAFNOSUPPORT, "Address family not supported by protocol family.");
1357    TEXT_FOR_ERROR(WSAEALREADY, "Operation already in progress.");
1358    TEXT_FOR_ERROR(WSAECONNABORTED, "Software caused connection abort.");
1359    TEXT_FOR_ERROR(WSAECONNREFUSED, "Connection refused.");
1360    TEXT_FOR_ERROR(WSAECONNRESET, "Connection reset by peer.");
1361    TEXT_FOR_ERROR(WSAEDESTADDRREQ, "Destination address required.");
1362    TEXT_FOR_ERROR(WSAEFAULT, "Bad address.");
1363    TEXT_FOR_ERROR(WSAEHOSTDOWN, "Host is down.");
1364    TEXT_FOR_ERROR(WSAEHOSTUNREACH, "No route to host.");
1365    TEXT_FOR_ERROR(WSAEINPROGRESS, "Operation now in progress.");
1366    TEXT_FOR_ERROR(WSAEINTR, "Interrupted function call.");
1367    TEXT_FOR_ERROR(WSAEINVAL, "Invalid argument.");
1368    TEXT_FOR_ERROR(WSAEISCONN, "Socket is already connected.");
1369    TEXT_FOR_ERROR(WSAEMFILE, "Too many open sockets.");
1370    TEXT_FOR_ERROR(WSAEMSGSIZE, "Message too long.");
1371    TEXT_FOR_ERROR(WSAENETDOWN, "Network is down.");
1372    TEXT_FOR_ERROR(WSAENETRESET, "Network dropped connection on reset.");
1373    TEXT_FOR_ERROR(WSAENETUNREACH, "Network is unreachable.");
1374    TEXT_FOR_ERROR(WSAENOBUFS, "No buffer space available.");
1375    TEXT_FOR_ERROR(WSAENOPROTOOPT, "Bad protocol option.");
1376    TEXT_FOR_ERROR(WSAENOTCONN, "Socket is not connected.");
1377    TEXT_FOR_ERROR(WSAENOTSOCK, "Socket operation on non-socket.");
1378    TEXT_FOR_ERROR(WSAEOPNOTSUPP, "Operation not supported.");
1379    TEXT_FOR_ERROR(WSAEPFNOSUPPORT, "Protocol family not supported.");
1380    TEXT_FOR_ERROR(WSAEPROCLIM, "Too many processes.");
1381    TEXT_FOR_ERROR(WSAEPROTONOSUPPORT, "Protocol not supported.");
1382    TEXT_FOR_ERROR(WSAEPROTOTYPE, "Protocol wrong type for socket.");
1383    TEXT_FOR_ERROR(WSAESHUTDOWN, "Cannot send after socket shutdown.");
1384    TEXT_FOR_ERROR(WSAESOCKTNOSUPPORT, "Socket type not supported.");
1385    TEXT_FOR_ERROR(WSAETIMEDOUT, "Connection timed out.");
1386    TEXT_FOR_ERROR(WSAEWOULDBLOCK, "Resource temporarily unavailable.");
1387    TEXT_FOR_ERROR(WSAHOST_NOT_FOUND, "Host not found.");
1388    TEXT_FOR_ERROR(WSANOTINITIALISED, "Successful WSAStartup not yet performed.");
1389    TEXT_FOR_ERROR(WSANO_DATA, "Valid name, no data record of requested type.");
1390    TEXT_FOR_ERROR(WSANO_RECOVERY, "This is a non-recoverable error.");
1391    TEXT_FOR_ERROR(WSASYSNOTREADY, "Network subsystem is unavailable.");
1392    TEXT_FOR_ERROR(WSATRY_AGAIN, "Non-authoritative host not found.");
1393    TEXT_FOR_ERROR(WSAVERNOTSUPPORTED, "WINSOCK.DLL version out of range.");
1394    TEXT_FOR_ERROR(WSAEDISCON, "Graceful shutdown in progress.");
1395    /*
1396     * The following error codes are documented in the Microsoft WinSock
1397     * reference guide, but don't actually exist.
1398     *
1399     * TEXT_FOR_ERROR(WSA_INVALID_HANDLE, "Specified event object handle is invalid.");
1400     * TEXT_FOR_ERROR(WSA_INVALID_PARAMETER, "One or more parameters are invalid.");
1401     * TEXT_FOR_ERROR(WSAINVALIDPROCTABLE, "Invalid procedure table from service provider.");
1402     * TEXT_FOR_ERROR(WSAINVALIDPROVIDER, "Invalid service provider version number.");
1403     * TEXT_FOR_ERROR(WSA_IO_PENDING, "Overlapped operations will complete later.");
1404     * TEXT_FOR_ERROR(WSA_IO_INCOMPLETE, "Overlapped I/O event object not in signaled state.");
1405     * TEXT_FOR_ERROR(WSA_NOT_ENOUGH_MEMORY, "Insufficient memory available.");
1406     * TEXT_FOR_ERROR(WSAPROVIDERFAILEDINIT, "Unable to initialize a service provider.");
1407     * TEXT_FOR_ERROR(WSASYSCALLFAILURE, "System call failure.");
1408     * TEXT_FOR_ERROR(WSA_OPERATION_ABORTED, "Overlapped operation aborted.");
1409     */
1410
1411    sprintf(tmp_buf, "(error number %d)", errcode);
1412    return tmp_buf;
1413 }
1414 #endif /* def _WIN32 */
1415
1416
1417 #ifdef __OS2__
1418 /*********************************************************************
1419  *
1420  * Function    :  os2_socket_strerr
1421  *
1422  * Description :  Translate the return value from sock_errno()
1423  *                into a string.
1424  *
1425  * Parameters  :
1426  *          1  :  errcode = The return value from sock_errno().
1427  *          2  :  tmp_buf = A temporary buffer that might be used to
1428  *                          store the string.
1429  *
1430  * Returns     :  String representing the error code.  This may be
1431  *                a global string constant or a string stored in
1432  *                tmp_buf.
1433  *
1434  *********************************************************************/
1435 static char *os2_socket_strerr(int errcode, char *tmp_buf)
1436 {
1437 #define TEXT_FOR_ERROR(code,text) \
1438    if (errcode == code)           \
1439    {                              \
1440       return #code " - " text;    \
1441    }
1442
1443    TEXT_FOR_ERROR(SOCEPERM          , "Not owner.")
1444    TEXT_FOR_ERROR(SOCESRCH          , "No such process.")
1445    TEXT_FOR_ERROR(SOCEINTR          , "Interrupted system call.")
1446    TEXT_FOR_ERROR(SOCENXIO          , "No such device or address.")
1447    TEXT_FOR_ERROR(SOCEBADF          , "Bad file number.")
1448    TEXT_FOR_ERROR(SOCEACCES         , "Permission denied.")
1449    TEXT_FOR_ERROR(SOCEFAULT         , "Bad address.")
1450    TEXT_FOR_ERROR(SOCEINVAL         , "Invalid argument.")
1451    TEXT_FOR_ERROR(SOCEMFILE         , "Too many open files.")
1452    TEXT_FOR_ERROR(SOCEPIPE          , "Broken pipe.")
1453    TEXT_FOR_ERROR(SOCEWOULDBLOCK    , "Operation would block.")
1454    TEXT_FOR_ERROR(SOCEINPROGRESS    , "Operation now in progress.")
1455    TEXT_FOR_ERROR(SOCEALREADY       , "Operation already in progress.")
1456    TEXT_FOR_ERROR(SOCENOTSOCK       , "Socket operation on non-socket.")
1457    TEXT_FOR_ERROR(SOCEDESTADDRREQ   , "Destination address required.")
1458    TEXT_FOR_ERROR(SOCEMSGSIZE       , "Message too long.")
1459    TEXT_FOR_ERROR(SOCEPROTOTYPE     , "Protocol wrong type for socket.")
1460    TEXT_FOR_ERROR(SOCENOPROTOOPT    , "Protocol not available.")
1461    TEXT_FOR_ERROR(SOCEPROTONOSUPPORT, "Protocol not supported.")
1462    TEXT_FOR_ERROR(SOCESOCKTNOSUPPORT, "Socket type not supported.")
1463    TEXT_FOR_ERROR(SOCEOPNOTSUPP     , "Operation not supported.")
1464    TEXT_FOR_ERROR(SOCEPFNOSUPPORT   , "Protocol family not supported.")
1465    TEXT_FOR_ERROR(SOCEAFNOSUPPORT   , "Address family not supported by protocol family.")
1466    TEXT_FOR_ERROR(SOCEADDRINUSE     , "Address already in use.")
1467    TEXT_FOR_ERROR(SOCEADDRNOTAVAIL  , "Can't assign requested address.")
1468    TEXT_FOR_ERROR(SOCENETDOWN       , "Network is down.")
1469    TEXT_FOR_ERROR(SOCENETUNREACH    , "Network is unreachable.")
1470    TEXT_FOR_ERROR(SOCENETRESET      , "Network dropped connection on reset.")
1471    TEXT_FOR_ERROR(SOCECONNABORTED   , "Software caused connection abort.")
1472    TEXT_FOR_ERROR(SOCECONNRESET     , "Connection reset by peer.")
1473    TEXT_FOR_ERROR(SOCENOBUFS        , "No buffer space available.")
1474    TEXT_FOR_ERROR(SOCEISCONN        , "Socket is already connected.")
1475    TEXT_FOR_ERROR(SOCENOTCONN       , "Socket is not connected.")
1476    TEXT_FOR_ERROR(SOCESHUTDOWN      , "Can't send after socket shutdown.")
1477    TEXT_FOR_ERROR(SOCETOOMANYREFS   , "Too many references: can't splice.")
1478    TEXT_FOR_ERROR(SOCETIMEDOUT      , "Operation timed out.")
1479    TEXT_FOR_ERROR(SOCECONNREFUSED   , "Connection refused.")
1480    TEXT_FOR_ERROR(SOCELOOP          , "Too many levels of symbolic links.")
1481    TEXT_FOR_ERROR(SOCENAMETOOLONG   , "File name too long.")
1482    TEXT_FOR_ERROR(SOCEHOSTDOWN      , "Host is down.")
1483    TEXT_FOR_ERROR(SOCEHOSTUNREACH   , "No route to host.")
1484    TEXT_FOR_ERROR(SOCENOTEMPTY      , "Directory not empty.")
1485    TEXT_FOR_ERROR(SOCEOS2ERR        , "OS/2 Error.")
1486
1487    sprintf(tmp_buf, "(error number %d)", errcode);
1488    return tmp_buf;
1489 }
1490 #endif /* def __OS2__ */
1491
1492
1493 /*
1494   Local Variables:
1495   tab-width: 3
1496   end:
1497 */